dev/migrate forms #5

Merged
jonasclaes merged 13 commits from dev/migrate-forms into main 2025-07-28 20:10:41 +00:00
jonasclaes commented 2025-07-28 20:06:38 +00:00 (Migrated from github.com)

Summary by CodeRabbit

New Features

  • Introduced a fully typed, reactive form system with Zod v4 validation, including new Svelte components for fields, labels, errors, and descriptions.
  • Added comprehensive documentation for the form system and overall project architecture.
  • Expanded VS Code extension recommendations to improve development experience.

Improvements

  • Refactored project-related dialogs (create, edit, delete) to use the new form system, enhancing validation, error handling, and UI consistency.
  • Updated sign-in form to use latest Zod adapter and improved error rendering.
  • Enhanced ESLint configuration for better Svelte and TypeScript support.
  • Upgraded multiple dependencies for improved stability and features.

Bug Fixes

  • Simplified team state management in shared components for more reliable team selection.

Chores

  • Updated Docker Compose configuration to specify container user.
  • Improved VS Code workspace settings for code formatting and linting.
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit **New Features** * Introduced a fully typed, reactive form system with Zod v4 validation, including new Svelte components for fields, labels, errors, and descriptions. * Added comprehensive documentation for the form system and overall project architecture. * Expanded VS Code extension recommendations to improve development experience. **Improvements** * Refactored project-related dialogs (create, edit, delete) to use the new form system, enhancing validation, error handling, and UI consistency. * Updated sign-in form to use latest Zod adapter and improved error rendering. * Enhanced ESLint configuration for better Svelte and TypeScript support. * Upgraded multiple dependencies for improved stability and features. **Bug Fixes** * Simplified team state management in shared components for more reliable team selection. **Chores** * Updated Docker Compose configuration to specify container user. * Improved VS Code workspace settings for code formatting and linting. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
coderabbitai[bot] commented 2025-07-28 20:06:45 +00:00 (Migrated from github.com)

Caution

Review failed

The pull request is closed.

Walkthrough

This update introduces a comprehensive, type-safe form system built with Svelte 5 and Zod 4, replacing the previous form management approach in key components. It adds new form components, utilities, and documentation, refactors project dialog forms to use the new system, updates workspace and linting configurations, and upgrades several dependencies.

Changes

Cohort / File(s) Change Summary
VSCode Configuration
.vscode/extensions.json, .vscode/settings.json
Expanded recommended extensions for Svelte, Prettier, ESLint, Playwright, GitHub Actions, Tailwind CSS, Vitest; added ESLint code actions on save.
Documentation
CLAUDE.md, src/lib/form/README.md
Major expansion of project and form system documentation, including architecture, workflow, and detailed form usage and API.
Docker Compose
compose.dev.override.yml
Set backend container user to UID/GID 1000 for development consistency.
Linting and Dependency Upgrades
eslint.config.js, package.json
Updated ESLint config for Svelte 5, expanded file matching, improved parser options; upgraded multiple dependencies (notably Zod v4, TypeScript beta, Svelte, TanStack, ESLint, Prettier, etc.).
Form System Implementation
src/lib/form/form.svelte.ts, src/lib/form/field.context.svelte.ts, src/lib/form/index.ts
Introduced a new, fully type-safe, Zod 4-based form system with context utilities and central exports.
Form System Components
src/lib/form/field.svelte, src/lib/form/field-label.svelte, src/lib/form/field-errors.svelte, src/lib/form/field-description.svelte, src/lib/form/form-errors.svelte
Added new Svelte components for form fields, labels, errors, and descriptions, all tightly integrated with the new form system and Zod validation.
Form System Adoption in Project Dialogs
src/routes/(user)/projects/(components)/create-project-dialog.svelte, src/routes/(user)/projects/(components)/edit-project-dialog.svelte, src/routes/(user)/projects/(components)/delete-project-dialog.svelte
Refactored project dialog components to use the new form system, updating all validation, error handling, and UI bindings.
Sign-in Form Validation Update
src/routes/(user)/auth/login/_components/sign-in-form.svelte
Updated to use new Zod 4 adapters for validation; improved error rendering with keyed iteration.
Team State Component Simplification
src/lib/components/shared/team-state.svelte
Simplified store usage and conditional checks for team selection logic.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant SvelteComponent as Form Component
    participant FormSystem as createForm (Zod 4)
    participant Backend

    User->>SvelteComponent: Fill and submit form
    SvelteComponent->>FormSystem: form.props.onsubmit
    FormSystem->>FormSystem: Validate fields with Zod 4
    alt Validation passes
        FormSystem->>Backend: Submit form data
        Backend-->>FormSystem: Success/Failure
        FormSystem-->>SvelteComponent: Update state/errors
    else Validation fails
        FormSystem-->>SvelteComponent: Show validation errors
    end
    SvelteComponent-->>User: Display errors or success

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Poem

🐇
In fields of forms, I hop with glee,
Zod and Svelte bring type safety to me!
Dialogs refactored, errors now clear,
Docs and configs shine—our path is sincere.
With every new component, I wiggle my nose—
This garden of code just beautifully grows!
🌱

Note

️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b0adf3c27c and 6993885dc1.

Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (20)
  • .vscode/extensions.json (1 hunks)
  • .vscode/settings.json (1 hunks)
  • CLAUDE.md (2 hunks)
  • compose.dev.override.yml (1 hunks)
  • eslint.config.js (3 hunks)
  • package.json (2 hunks)
  • src/lib/components/shared/team-state.svelte (1 hunks)
  • src/lib/form/README.md (1 hunks)
  • src/lib/form/field-description.svelte (1 hunks)
  • src/lib/form/field-errors.svelte (1 hunks)
  • src/lib/form/field-label.svelte (1 hunks)
  • src/lib/form/field.context.svelte.ts (1 hunks)
  • src/lib/form/field.svelte (1 hunks)
  • src/lib/form/form-errors.svelte (1 hunks)
  • src/lib/form/form.svelte.ts (1 hunks)
  • src/lib/form/index.ts (1 hunks)
  • src/routes/(user)/auth/login/_components/sign-in-form.svelte (2 hunks)
  • src/routes/(user)/projects/(components)/create-project-dialog.svelte (4 hunks)
  • src/routes/(user)/projects/(components)/delete-project-dialog.svelte (3 hunks)
  • src/routes/(user)/projects/(components)/edit-project-dialog.svelte (3 hunks)
Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dev/migrate-forms

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 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.
    • Explain this complex logic.
    • 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 explain this code block.
    • @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 explain its main purpose.
    • @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.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

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 generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests 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.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

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.
<!-- This is an auto-generated comment: summarize by coderabbit.ai --> <!-- This is an auto-generated comment: failure by coderabbit.ai --> > [!CAUTION] > ## Review failed > > The pull request is closed. <!-- end of auto-generated comment: failure by coderabbit.ai --> <!-- walkthrough_start --> ## Walkthrough This update introduces a comprehensive, type-safe form system built with Svelte 5 and Zod 4, replacing the previous form management approach in key components. It adds new form components, utilities, and documentation, refactors project dialog forms to use the new system, updates workspace and linting configurations, and upgrades several dependencies. ## Changes | Cohort / File(s) | Change Summary | |------------------|---------------| | **VSCode Configuration**<br>`.vscode/extensions.json`, `.vscode/settings.json` | Expanded recommended extensions for Svelte, Prettier, ESLint, Playwright, GitHub Actions, Tailwind CSS, Vitest; added ESLint code actions on save. | | **Documentation**<br>`CLAUDE.md`, `src/lib/form/README.md` | Major expansion of project and form system documentation, including architecture, workflow, and detailed form usage and API. | | **Docker Compose**<br>`compose.dev.override.yml` | Set backend container user to UID/GID 1000 for development consistency. | | **Linting and Dependency Upgrades**<br>`eslint.config.js`, `package.json` | Updated ESLint config for Svelte 5, expanded file matching, improved parser options; upgraded multiple dependencies (notably Zod v4, TypeScript beta, Svelte, TanStack, ESLint, Prettier, etc.). | | **Form System Implementation**<br>`src/lib/form/form.svelte.ts`, `src/lib/form/field.context.svelte.ts`, `src/lib/form/index.ts` | Introduced a new, fully type-safe, Zod 4-based form system with context utilities and central exports. | | **Form System Components**<br>`src/lib/form/field.svelte`, `src/lib/form/field-label.svelte`, `src/lib/form/field-errors.svelte`, `src/lib/form/field-description.svelte`, `src/lib/form/form-errors.svelte` | Added new Svelte components for form fields, labels, errors, and descriptions, all tightly integrated with the new form system and Zod validation. | | **Form System Adoption in Project Dialogs**<br>`src/routes/(user)/projects/(components)/create-project-dialog.svelte`, `src/routes/(user)/projects/(components)/edit-project-dialog.svelte`, `src/routes/(user)/projects/(components)/delete-project-dialog.svelte` | Refactored project dialog components to use the new form system, updating all validation, error handling, and UI bindings. | | **Sign-in Form Validation Update**<br>`src/routes/(user)/auth/login/_components/sign-in-form.svelte` | Updated to use new Zod 4 adapters for validation; improved error rendering with keyed iteration. | | **Team State Component Simplification**<br>`src/lib/components/shared/team-state.svelte` | Simplified store usage and conditional checks for team selection logic. | ## Sequence Diagram(s) ```mermaid sequenceDiagram participant User participant SvelteComponent as Form Component participant FormSystem as createForm (Zod 4) participant Backend User->>SvelteComponent: Fill and submit form SvelteComponent->>FormSystem: form.props.onsubmit FormSystem->>FormSystem: Validate fields with Zod 4 alt Validation passes FormSystem->>Backend: Submit form data Backend-->>FormSystem: Success/Failure FormSystem-->>SvelteComponent: Update state/errors else Validation fails FormSystem-->>SvelteComponent: Show validation errors end SvelteComponent-->>User: Display errors or success ``` ## Estimated code review effort 🎯 4 (Complex) | ⏱️ ~40 minutes ## Poem > 🐇 > In fields of forms, I hop with glee, > Zod and Svelte bring type safety to me! > Dialogs refactored, errors now clear, > Docs and configs shine—our path is sincere. > With every new component, I wiggle my nose— > This garden of code just beautifully grows! > 🌱✨ <!-- walkthrough_end --> <!-- internal state start --> <!-- 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 --> <!-- internal state end --> <!-- announcements_start --> > [!NOTE] > <details open="true"> > <summary>⚡️ Unit Test Generation is now available in beta!</summary> > > Learn more [here](https://docs.coderabbit.ai/finishing-touches/unit-test-generation), or try it out under "Finishing Touches" below. > > </details> <!-- announcements_end --> --- <details> <summary>📜 Recent review details</summary> **Configuration used: CodeRabbit UI** **Review profile: CHILL** **Plan: Pro** <details> <summary>📥 Commits</summary> Reviewing files that changed from the base of the PR and between b0adf3c27cdf9d6603dd10b3a8ab556e8d74e45a and 6993885dc1de4a9ea7383df3309c0650a239fe3e. </details> <details> <summary>⛔ Files ignored due to path filters (1)</summary> * `pnpm-lock.yaml` is excluded by `!**/pnpm-lock.yaml` </details> <details> <summary>📒 Files selected for processing (20)</summary> * `.vscode/extensions.json` (1 hunks) * `.vscode/settings.json` (1 hunks) * `CLAUDE.md` (2 hunks) * `compose.dev.override.yml` (1 hunks) * `eslint.config.js` (3 hunks) * `package.json` (2 hunks) * `src/lib/components/shared/team-state.svelte` (1 hunks) * `src/lib/form/README.md` (1 hunks) * `src/lib/form/field-description.svelte` (1 hunks) * `src/lib/form/field-errors.svelte` (1 hunks) * `src/lib/form/field-label.svelte` (1 hunks) * `src/lib/form/field.context.svelte.ts` (1 hunks) * `src/lib/form/field.svelte` (1 hunks) * `src/lib/form/form-errors.svelte` (1 hunks) * `src/lib/form/form.svelte.ts` (1 hunks) * `src/lib/form/index.ts` (1 hunks) * `src/routes/(user)/auth/login/_components/sign-in-form.svelte` (2 hunks) * `src/routes/(user)/projects/(components)/create-project-dialog.svelte` (4 hunks) * `src/routes/(user)/projects/(components)/delete-project-dialog.svelte` (3 hunks) * `src/routes/(user)/projects/(components)/edit-project-dialog.svelte` (3 hunks) </details> </details> <!-- finishing_touch_checkbox_start --> <details> <summary>✨ Finishing Touches</summary> - [ ] <!-- {"checkboxId": "7962f53c-55bc-4827-bfbf-6a18da830691"} --> 📝 Generate Docstrings <details> <summary>🧪 Generate unit tests</summary> - [ ] <!-- {"checkboxId": "f47ac10b-58cc-4372-a567-0e02b2c3d479", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Create PR with unit tests - [ ] <!-- {"checkboxId": "07f1e7d6-8a8e-4e23-9900-8731c2c87f58", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Post copyable unit tests in a comment - [ ] <!-- {"checkboxId": "6ba7b810-9dad-11d1-80b4-00c04fd430c8", "radioGroupId": "utg-output-choice-group-unknown_comment_id"} --> Commit unit tests in branch `dev/migrate-forms` </details> </details> <!-- finishing_touch_checkbox_end --> <!-- tips_start --> --- Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. <details> <summary>❤️ Share</summary> - [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai) - [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai) - [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai) - [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code) </details> <details> <summary>🪧 Tips</summary> ### Chat There are 3 ways to chat with [CodeRabbit](https://coderabbit.ai?utm_source=oss&utm_medium=github&utm_campaign=DocPort-io/app&utm_content=5): - Review comments: Directly reply to a review comment made by CodeRabbit. Example: - `I pushed a fix in commit <commit_id>, please review it.` - `Explain this complex logic.` - `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 explain this code block.` - `@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 explain its main purpose.` - `@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.` ### Support Need help? Create a ticket on our [support page](https://www.coderabbit.ai/contact-us/support) for assistance with any issues or questions. 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](https://docs.coderabbit.ai/finishing-touches/docstrings) for this PR. - `@coderabbitai generate sequence diagram` to generate a sequence diagram of the changes in this PR. - `@coderabbitai generate unit tests` to generate unit tests 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. ### CodeRabbit Configuration File (`.coderabbit.yaml`) - You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository. - Please see the [configuration documentation](https://docs.coderabbit.ai/guides/configure-coderabbit) for more information. - If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json` ### Documentation and Community - Visit our [Documentation](https://docs.coderabbit.ai) for detailed information on how to use CodeRabbit. - Join our [Discord Community](http://discord.gg/coderabbit) to get help, request features, and share feedback. - Follow us on [X/Twitter](https://twitter.com/coderabbitai) for updates and announcements. </details> <!-- tips_end -->
copilot-pull-request-reviewer[bot] (Migrated from github.com) reviewed 2025-07-28 20:07:48 +00:00
copilot-pull-request-reviewer[bot] (Migrated from github.com) left a comment

Pull Request Overview

This PR migrates the application from sveltekit-superforms to a custom form system built with Svelte 5 runes and Zod v4. The migration modernizes form handling with improved type safety and developer experience while upgrading dependencies.

  • Replaces superforms with custom form system using Svelte 5 runes and Zod v4
  • Updates all project-related dialogs to use the new form system
  • Upgrades dependencies including Svelte, TypeScript, ESLint, and other core packages

Reviewed Changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/lib/form/ New custom form system with field components and validation
src/routes/(user)/projects/(components)/ Migrated dialog components to use new form system
src/routes/(user)/auth/login/_components/sign-in-form.svelte Updated to use zod4 adapters
package.json Major dependency upgrades including Zod v4 and Svelte 5.36
eslint.config.js Updated ESLint configuration for new package versions
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported
## Pull Request Overview This PR migrates the application from sveltekit-superforms to a custom form system built with Svelte 5 runes and Zod v4. The migration modernizes form handling with improved type safety and developer experience while upgrading dependencies. - Replaces superforms with custom form system using Svelte 5 runes and Zod v4 - Updates all project-related dialogs to use the new form system - Upgrades dependencies including Svelte, TypeScript, ESLint, and other core packages ### Reviewed Changes Copilot reviewed 20 out of 21 changed files in this pull request and generated 6 comments. <details> <summary>Show a summary per file</summary> | File | Description | | ---- | ----------- | | src/lib/form/ | New custom form system with field components and validation | | src/routes/(user)/projects/(components)/ | Migrated dialog components to use new form system | | src/routes/(user)/auth/login/_components/sign-in-form.svelte | Updated to use zod4 adapters | | package.json | Major dependency upgrades including Zod v4 and Svelte 5.36 | | eslint.config.js | Updated ESLint configuration for new package versions | </details> <details> <summary>Files not reviewed (1)</summary> * **pnpm-lock.yaml**: Language not supported </details>
@ -0,0 +1,546 @@
import type { z } from 'zod';
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-28 20:07:48 +00:00

The isSubmittable condition doesn't account for the hasErrors state. A form could be marked as valid but still have field-level errors that should prevent submission.

	const isSubmittable = $derived(isValid && !isValidating && !isSubmitting && !hasErrors);
The `isSubmittable` condition doesn't account for the `hasErrors` state. A form could be marked as valid but still have field-level errors that should prevent submission. ```suggestion const isSubmittable = $derived(isValid && !isValidating && !isSubmitting && !hasErrors); ```
@ -0,0 +289,4 @@
const getFieldValues = (): SchemaType => {
return Object.fromEntries(
Object.entries(fields).map(([key, field]) => [key, field.state.value])
) as SchemaType;
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-28 20:07:48 +00:00

Type assertion as SchemaType could mask type safety issues. Consider using proper type guards or validation to ensure the object structure matches the expected schema type.

		const rawValues = Object.fromEntries(
			Object.entries(fields).map(([key, field]) => [key, field.state.value])
		);

		// Validate the rawValues object against the SchemaType schema
		const schema: ZodObject<ZodRawShape> = z.object(SchemaTypeShape); // Assuming SchemaTypeShape is defined
		const result = schema.safeParse(rawValues);

		if (!result.success) {
			throw new Error('Validation failed for field values');
		}

		return result.data;
Type assertion `as SchemaType` could mask type safety issues. Consider using proper type guards or validation to ensure the object structure matches the expected schema type. ```suggestion const rawValues = Object.fromEntries( Object.entries(fields).map(([key, field]) => [key, field.state.value]) ); // Validate the rawValues object against the SchemaType schema const schema: ZodObject<ZodRawShape> = z.object(SchemaTypeShape); // Assuming SchemaTypeShape is defined const result = schema.safeParse(rawValues); if (!result.success) { throw new Error('Validation failed for field values'); } return result.data; ```
@ -86,0 +75,4 @@
<FieldLabel>{m.name()}</FieldLabel>
<Input
{...props}
bind:value={state.value}
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-28 20:07:48 +00:00

Non-null assertion on teamState.currentTeam! could cause runtime errors if no team is selected. Consider adding proper validation or error handling.

				team: teamState.currentTeam ?? null
Non-null assertion on `teamState.currentTeam!` could cause runtime errors if no team is selected. Consider adding proper validation or error handling. ```suggestion team: teamState.currentTeam ?? null ```
@ -60,0 +52,4 @@
variant="outline"
onclick={() => dialogController.close()}
disabled={form.state.isSubmitting}
>
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-28 20:07:47 +00:00

The non-null assertion operator is used on dialogController.data!.id, but the type definition shows dialogController expects ProjectDeleteSchema which should contain the id. This could cause runtime errors if dialogController.data is null or undefined.

				id: dialogController.data?.id ?? ''
The non-null assertion operator is used on `dialogController.data!.id`, but the type definition shows `dialogController` expects `ProjectDeleteSchema` which should contain the id. This could cause runtime errors if `dialogController.data` is null or undefined. ```suggestion id: dialogController.data?.id ?? '' ```
@ -128,0 +72,4 @@
<FieldErrors />
{/snippet}
</Field>
<Field {form} name="status">
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-28 20:07:47 +00:00

Using non-null assertion operator on dialogController.data!.id without proper null checking. This could cause runtime errors if the dialog is opened without proper data initialization.

					if (!dialogController.data) {
						throw new Error('Dialog data is not initialized.');
					}
					await $updateMutation.mutateAsync({
						id: dialogController.data.id,
Using non-null assertion operator on `dialogController.data!.id` without proper null checking. This could cause runtime errors if the dialog is opened without proper data initialization. ```suggestion if (!dialogController.data) { throw new Error('Dialog data is not initialized.'); } await $updateMutation.mutateAsync({ id: dialogController.data.id, ```
copilot-pull-request-reviewer[bot] (Migrated from github.com) commented 2025-07-28 20:07:48 +00:00

Missing spacing between the loading icon and text. The icon and text are concatenated without proper spacing, which could affect readability.

						<span class="flex items-center space-x-2">
							<LoaderCircle class="h-4 w-4 animate-spin" />
							<span>{m.saving()}</span>
						</span>
Missing spacing between the loading icon and text. The icon and text are concatenated without proper spacing, which could affect readability. ```suggestion <span class="flex items-center space-x-2"> <LoaderCircle class="h-4 w-4 animate-spin" /> <span>{m.saving()}</span> </span> ```
jonasclaes (Migrated from github.com) reviewed 2025-07-28 20:09:12 +00:00
@ -60,0 +52,4 @@
variant="outline"
onclick={() => dialogController.close()}
disabled={form.state.isSubmitting}
>
jonasclaes (Migrated from github.com) commented 2025-07-28 20:09:12 +00:00

Won't happen due to the UI forcing the selection of a project.

Won't happen due to the UI forcing the selection of a project.
coderabbitai[bot] (Migrated from github.com) approved these changes 2025-07-28 20:15:47 +00:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
DocPort/app-pb!5
No description provided.