Skip to content

ユーザー画面の再提出機能の実装#2042

Open
riririn180904 wants to merge 27 commits intogm3/developfrom
feat/riririn/2038-user-resubmission
Open

ユーザー画面の再提出機能の実装#2042
riririn180904 wants to merge 27 commits intogm3/developfrom
feat/riririn/2038-user-resubmission

Conversation

@riririn180904
Copy link
Copy Markdown
Collaborator

@riririn180904 riririn180904 commented May 6, 2026

対応Issue

resolve #2038

概要

  • ユーザー画面の再提出機能の追加

実装詳細

  • ユーザー画面の各申請のステータスに再提出を追加
  • 再提出のとき、受付期間を過ぎても編集できるように変更
  • 再提出後は編集不可状態になるように変更
  • 再提出後はステータスが登録済(DBでは未確認)になるように変更

画面スクリーンショット等

テスト項目

  • [ ]
  • [ ]
  • [ ]

備考

火気使用申請のみ受付期間の切り替えができなかったので動作確認できてません

Summary by CodeRabbit

  • New Features

    • Resubmission workflow: users can edit and resubmit applications in a new "resubmission" state across application types; UI shows an explicit resubmission flow and enables edit actions during resubmission.
  • Localization

    • Added English and Japanese translations for the new "resubmission" status.
  • Style

    • Introduced a new theme color token for consistent resubmission accent styling.

Review Change Stack

riririn180904 and others added 8 commits May 2, 2026 01:49
Co-authored-by: Copilot <copilot@github.com>
- isEdit の !isSubmission を isResubmission に修正(ロジックが逆だった)
- onEdit も再提出待ち時に渡すよう修正
- AccordionMenu の isEdit に再提出待ち条件を追加
- isEditing の初期値を false に戻す(誤って true で初期化していた)
- isFormListMode を isEmployeesData && !isEditing にシンプル化
- APIは { group, submissions: [...] } を返すが単一オブジェクトとして扱っていた
- Rails enumはJSON上で文字列("waiting_resubmission")で返るため数値変換マップを追加
- submissions配列からemployeeのエントリを探して返すよう修正
- APIエンドポイントのURLを修正し、末尾のスラッシュを削除
- healthCenterSubmissionStatusの型定義を明確化し、可読性を向上
- injectパッケージを削除
- coffee-scriptパッケージの削除に伴う関連エントリをpackage-lock.jsonから削除
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 6, 2026

Caution

Review failed

An error occurred during the review process. Please try again later.

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: bb9017a3-3735-4dbb-889f-a58b4ef326b5

📥 Commits

Reviewing files that changed from the base of the PR and between 1d8a939 and 4a50333.

📒 Files selected for processing (1)
  • .github/workflows/user-code-quality.yml
💤 Files with no reviewable changes (1)
  • .github/workflows/user-code-quality.yml

📝 Walkthrough

Walkthrough

This PR implements a resubmission workflow for the user dashboard: it adds a health-center submission status API and APPLICATION_STATUS constants, introduces a resubmission display status and locale strings, threads a status prop through application components and hooks, and updates deadline/edit logic to allow edits when status === 'waiting_resubmission'.

Changes

Resubmission Status Feature

Layer / File(s) Summary
API Types & Contracts
user/src/api/healthCenterSubmissionStatusApi.ts, user/src/utils/constants.ts
New health-center submission status API with types (HealthCenterSubmissionStatusResponse, HealthCenterSubmissionStatusApiResponse), endpoints for fetching and updating submission status, and APPLICATION_STATUS numeric constants.
Status Component & Localization
user/src/components/Status/Status.tsx, user/src/components/Status/hooks.ts, user/public/locales/en/common.json, user/public/locales/ja/common.json
ValidStatus registration union expanded to include resubmission; added styling and translation key; English and Japanese locale entries added.
Styling & Configuration
user/src/styles/globals.css, user/tailwind.config.ts
Adds CSS custom property --re-color: #ff8411`` (light/dark) and maps Tailwind re color to the CSS variable.
Accordion Menu Integration
user/src/components/AccordionMenu/AccordionMenu.tsx
Adds optional status prop; computes registerStatus as resubmission when status === 'waiting_resubmission'.
CookingProcessOrder
user/src/components/Applications/CookingProcessOrder/CookingProcessOrder.tsx, user/src/components/Applications/CookingProcessOrder/hooks.ts
Threads status through component and hook; allows submission/editing during resubmission deadline and updates submission status to unapproved after save.
Employees
user/src/components/Applications/Employees/Employees.tsx, user/src/components/Applications/Employees/hooks.ts
Adds status prop and isResubmission; changes edit affordance from !isDeadline to `!isDeadline
FireEquipment
user/src/components/Applications/FireEquipment/FireEquipment.tsx, user/src/components/Applications/FireEquipment/components/...
Threads status through component and hooks; splits deadline rendering between read-only and editable form for resubmission; updates equipment submission status after save.
FoodProduct
user/src/components/Applications/FoodProduct/FoodProduct.tsx, user/src/components/Applications/FoodProduct/hooks.ts
Adds status prop and isResubmission; renders form immediately when resubmitting; patches submission status after updates.
PurchaseLists
user/src/components/Applications/PurchaseLists/PurchaseLists.tsx, user/src/components/Applications/PurchaseLists/hooks.ts
Threads status through render paths; adds deadline branch to show editable PurchaseListsForm when status === 'waiting_resubmission'; patches submission status after save.
VenueMap
user/src/components/Applications/VenueMap/VenueMap.tsx, user/src/components/Applications/VenueMap/hooks.ts
Adds status to component and hook; exposes isResubmission and updateStatus; returns VenueMapForm early during resubmission and updates status asynchronously on submit.
Home Page Integration
user/src/pages/home/index.tsx
Fetches healthCenterSubmissionStatus via new hook, derives per-application submission objects by applicationType, and passes per-app status into the application components; groupId handling updated to allow undefined.
API Conditioning
user/src/api/checkAllRegisteredApi.ts
Conditional endpoint building: returns null when groupId is undefined to avoid invalid requests.
Cleanup
admin_view/nuxt-project/package.json, .github/workflows/user-code-quality.yml
Removed unused inject dependency; updated GitHub Actions Node setup to v22 and removed pnpm cache config.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • NUTFes/group-manager-2#2023: Server-side API controller, routes, and status enum implementation corresponding to this PR's client-side submission status API and status type additions.
  • NUTFes/group-manager-2#1925: Previous FireEquipment feature modifications affecting the same component files and hook integration patterns.

Suggested reviewers

  • hikahana
  • KokiWakatsuki

"🐰 Hops past the resubmission flow,
Status flags glow orange and bright,
Hooks and forms now dance at night,
Edits return when admins call,
Unapproved resets, we patch them all!"

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The PR description addresses the main objective but lacks critical details. Most template sections remain unfilled with concrete information. Complete the implementation details with specific technical changes, add test items and screenshots, and explain the limitation with fire equipment deadline switching.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The PR title "ユーザー画面の再提出機能の実装" (User screen resubmission feature implementation) clearly and directly describes the main purpose of the changeset, which is implementing resubmission functionality in the user interface.
Linked Issues check ✅ Passed The PR implements the core resubmission workflow across multiple components (status display, conditional editing, status updates), API integration for submission status management, locale translations for resubmission state, and UI styling.
Out of Scope Changes check ✅ Passed All changes directly support the resubmission feature: status management APIs, component updates for resubmission handling, locale additions, styling tokens, status type definitions, and dependency cleanup.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/riririn/2038-user-resubmission

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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

Comment @coderabbitai help to get the list of available commands and usage tips.

@riririn180904 riririn180904 changed the title Feat/riririn/2038 user resubmission ユーザー画面の再提出機能の実装 May 10, 2026
@riririn180904 riririn180904 marked this pull request as ready for review May 10, 2026 22:03
Copy link
Copy Markdown

@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: 14

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (4)
user/src/components/Applications/FireEquipment/components/hooks.ts (1)

139-188: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Apply the resubmission status transition to the “火気不使用” submit path too.

The new updateStatus() flow is only used from onSubmitFireEquipment. If the user resubmits by changing this application to “火気不使用”, onSubmitUnregistered succeeds without clearing waiting_resubmission, so the application can stay stuck in the resubmission state.

Suggested fix
       await mutateFireEquipmentOrder();
+      if (status === 'waiting_resubmission') {
+        await updateStatus('unapproved');
+      }
       toast.success('火気申請を行わない登録が完了しました');
       handleEditCancel?.();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/components/Applications/FireEquipment/components/hooks.ts` around
lines 139 - 188, The resubmission status transition is only applied in
onSubmitFireEquipment, so when a user submits via the “火気不使用” path handled by
onSubmitUnregistered the health-center status can remain waiting_resubmission;
update onSubmitUnregistered to mirror onSubmitFireEquipment’s behavior by
calling updateStatus('unapproved') after the successful submit (after post/patch
and mutateFireEquipmentOrder/mutate equivalent and toast), guarded by if (status
=== 'waiting_resubmission'); use the existing updateStatus function to perform
the patch and subsequent mutateHealthCenterSubmissionStatus.
user/src/components/Applications/FoodProduct/hooks.ts (1)

153-178: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Don’t treat a saved product update as a failed submit just because the status patch broke.

By the time updateStatus() runs here, the deletes/upsert and mutateFoodProducts() have already completed. If the status request fails, the outer catch still shows the generic update error for an operation that was already persisted, which makes duplicate retries much more likely.

Suggested fix
       await upsertFoodProducts({
         body: { food_products: apiProducts },
       });

       // データを強制的に再取得(optimistic updateではなく確実な更新)
       await mutateFoodProducts();
@@
-      // 再提出完了時
-      if (status === 'waiting_resubmission') {
-        // status更新処理
-        await updateStatus('unapproved');
-      }
-
       // 成功時のみビューモードに戻す
       setIsEditing(false);

       toast.success(t('applications.foodProduct.messages.updateSuccess'), {
         position: 'top-right',
         autoClose: 3000,
       });
+
+      if (status === 'waiting_resubmission') {
+        try {
+          await updateStatus('unapproved');
+        } catch (statusError) {
+          console.error('販売品ステータス更新エラー:', statusError);
+        }
+      }
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/components/Applications/FoodProduct/hooks.ts` around lines 153 -
178, The current flow runs upsertFoodProducts and mutateFoodProducts then calls
updateStatus and if updateStatus fails the outer catch treats the whole
operation as failed; change this so updateStatus('unapproved') is awaited inside
its own try/catch (only when status === 'waiting_resubmission') and handle its
error separately—e.g., log or show a non-blocking warning toast instead of
throwing—so success path (setIsEditing(false), success toast) runs when the
upsert/mutate completed; locate the block around upsertFoodProducts,
mutateFoodProducts, updateStatus, and status === 'waiting_resubmission' to
implement the isolated try/catch.
user/src/pages/home/index.tsx (2)

367-388: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Inconsistent groupId fallback pattern.

Lines 367, 378, and 388 use groupId || 0, which converts undefined back to 0. This seems inconsistent with the change at line 351 where groupId is allowed to be undefined. If undefined is a valid state, the API hooks should handle it; if 0 is the correct fallback, then line 351 should use ?? 0.

🔧 Suggested fix

Either revert line 351:

-  const groupId = groupUserIdAndGroupCategoryId?.id ?? undefined;
+  const groupId = groupUserIdAndGroupCategoryId?.id ?? 0;

Or remove the fallbacks and ensure child components handle undefined:

-          groupId={groupId || 0}
+          groupId={groupId}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/pages/home/index.tsx` around lines 367 - 388, There is an
inconsistent fallback for groupId: some places pass groupId || 0 while earlier
code allows groupId to be undefined; pick one approach and make it consistent —
either (A) enforce a 0 default at the source (set the parent variable to use
nullish coalescing, e.g. groupId = incomingGroupId ?? 0) so all children
(ViceRepresentative, GroupCategoryContent and any other consumers using the
groupId prop) can safely rely on a numeric id, or (B) remove the inline
fallbacks (drop the "|| 0" in the props for ViceRepresentative and
GroupCategoryContent and anywhere else) and update those child components (their
prop types/handlers) to accept undefined and handle that state; update the
symbol(s) ViceRepresentative, GroupCategoryContent and any mutate* callers
accordingly so the behavior is uniform.

162-339: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Status prop not being threaded to resubmission-enabled components in other categories.

VenueMap, FoodProduct, and FireEquipment components accept a status?: string prop and implement resubmission logic (derivable from their hooks), but only the FOOD_SALES category extracts submission status data and threads it to these components. The GOODS_SALES, RESEARCH_LAB, EXHIBITION, and COMMITTEE categories use these same components without the status prop, leaving their resubmission feature inactive.

Clarify whether resubmission is intentionally limited to food sales only, or if other categories should also derive and pass submission status to enable resubmission functionality for their respective components.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/pages/home/index.tsx` around lines 162 - 339, The VenueMap,
FoodProduct, and FireEquipment components accept a status?: string prop used to
enable resubmission, but in the GOODS_SALES, RESEARCH_LAB, EXHIBITION, and
COMMITTEE branches you are not passing status (only FOOD_SALES does), disabling
resubmission; fix this by deriving the submission status in those branches the
same way you do in the FOOD_SALES branch and pass it into the components as
status={...} (update the VenueMap, FoodProduct, and FireEquipment JSX in the
GOODS_SALES, RESEARCH_LAB, EXHIBITION, and COMMITTEE branches to include the
status prop, using the same status source logic used for FOOD_SALES so
resubmission logic activates where appropriate).
🧹 Nitpick comments (4)
user/src/api/healthCenterSubmissionStatusApi.ts (1)

43-47: ⚡ Quick win

Avoid raw string for submission status.

The status field is currently string, but downstream logic depends on specific literals (e.g. waiting_resubmission). Defining a status union here will tighten type safety across the flow.

💡 Suggested refactor
+export type HealthCenterSubmissionStatus =
+  | 'unapproved'
+  | 'waiting_resubmission'
+  | 'approved'
+  | 'unsubmitted';
+
 export type HealthCenterSubmissionStatusResponse = {
   id: number;
   group_id: number;
   applicationType: string;
-  status: string;
+  status: HealthCenterSubmissionStatus;
   createdAt: string;
   updatedAt: string;
 };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/api/healthCenterSubmissionStatusApi.ts` around lines 43 - 47, The
status field in HealthCenterSubmissionStatusResponse should not be a raw string;
define a typed union (e.g., export a SubmissionStatus type with the allowed
literals such as "waiting_resubmission" and the other known status values) and
replace status: string with status: SubmissionStatus; update any related usages
to import/use SubmissionStatus so downstream code has strict literal typing.
user/src/components/Applications/VenueMap/hooks.ts (1)

35-35: ⚡ Quick win

Replace magic string with a constant or enum.

The string literal 'unapproved' is used as a type constraint and passed directly. Define this as a constant or use an enum to prevent typos and improve maintainability.

♻️ Use constants
+const APPLICATION_STATUS = {
+  UNAPPROVED: 'unapproved',
+  APPROVED: 'approved',
+  WAITING_RESUBMISSION: 'waiting_resubmission',
+} as const;
+
-const updateStatus = async (status: 'unapproved') => {
+const updateStatus = async (status: typeof APPLICATION_STATUS.UNAPPROVED) => {
   const venueMapSubmission = healthCenterSubmissionStatus.find(
     (submission) => submission.applicationType === 'venue_map'
   );

   // ...
   await patchHealthCenterSubmissionStatus({
     id: venueMapSubmission.id,
     body: { status },
   });
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/components/Applications/VenueMap/hooks.ts` at line 35, The
updateStatus function currently uses the literal 'unapproved' as both a type and
value; define a shared constant or enum (e.g., VenueStatus with UNAPPROVED) and
replace the literal in the updateStatus signature and all callers where
'unapproved' is passed; update any related type annotations or imports to
reference the new VenueStatus constant/enum so callers use
VenueStatus.UNAPPROVED instead of the magic string.
user/src/pages/home/index.tsx (1)

82-99: ⚡ Quick win

Optimize multiple find() calls with a lookup map.

Lines 82-99 perform six separate .find() calls on healthCenterSubmissionStatus. This is inefficient and could be replaced with a single pass to build a lookup object.

♻️ Optimize with a lookup map
  if (groupCategoryId === GROUP_CATEGORY.FOOD_SALES) {
-   const employeeSubmission = healthCenterSubmissionStatus?.find(
-     (s) => s.applicationType === 'employee'
-   );
-   const foodProductsSubmission = healthCenterSubmissionStatus?.find(
-     (s) => s.applicationType === 'food_product'
-   );
-   // ... etc
+   const submissionByType = healthCenterSubmissionStatus?.reduce(
+     (acc, submission) => {
+       acc[submission.applicationType] = submission;
+       return acc;
+     },
+     {} as Record<string, HealthCenterSubmissionStatusResponse>
+   ) ?? {};
+
+   const employeeSubmission = submissionByType['employee'];
+   const foodProductsSubmission = submissionByType['food_product'];
+   const purchaseListsSubmission = submissionByType['purchase_list'];
+   const venueMapSubmission = submissionByType['venue_map'];
+   const cookingProcessOrderSubmission = submissionByType['cooking_process_order'];
+   const fireEquipmentSubmission = submissionByType['equipment'];
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/pages/home/index.tsx` around lines 82 - 99, Multiple .find() calls
over healthCenterSubmissionStatus (used to create employeeSubmission,
foodProductsSubmission, purchaseListsSubmission, venueMapSubmission,
cookingProcessOrderSubmission, fireEquipmentSubmission) cause repeated
iteration; replace them with a single pass that builds a lookup (e.g., reduce
into an object or a Map keyed by applicationType) and then reference
lookup['employee'], lookup['food_product'], etc.; update the variables to pull
from that lookup (employeeSubmission = lookup['employee'], etc.) so you iterate
the array only once.
user/src/components/Applications/Employees/hooks.ts (1)

401-401: ⚡ Quick win

Replace magic string with a constant.

Same as in VenueMap/hooks.ts — use a constant or enum for 'unapproved'.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/components/Applications/Employees/hooks.ts` at line 401, The
updateStatus function currently uses the magic string 'unapproved'; replace this
literal with a shared constant or enum (e.g., STATUS_UNAPPROVED or an
EmployeeStatus enum) to match the pattern used in VenueMap/hooks.ts. Update the
function signature and any call sites that pass or compare 'unapproved' to
import and use the new constant/enum, and ensure TypeScript types are adjusted
(union or enum type) so updateStatus accepts the constant/enum value instead of
the raw string.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@user/src/api/healthCenterSubmissionStatusApi.ts`:
- Around line 66-68: The endpoint construction uses a truthy check on groupId
which incorrectly treats 0 as absent; update the conditional in the endpoint
assignment to use a nullish check (e.g., groupId != null) so that values like 0
are allowed, keeping the reference to
API_ENDPOINTS.HEALTH_CENTER_SUBMISSION_STATUS and the endpoint constant
(endpoint) and groupId identifier intact.

In `@user/src/components/Applications/CookingProcessOrder/hooks.ts`:
- Around line 151-166: The status patch is performed before persisting data, so
if upsertCookingProcessOrders fails the submission stays in
waiting_resubmission; change the order so patchHealthCenterSubmissionStatus (and
mutateHealthCenterSubmissionStatus) is called only after await
upsertCookingProcessOrders completes successfully. Locate updateStatus and the
code path that calls upsertCookingProcessOrders (and the similar block around
lines 183-191), move the await patchHealthCenterSubmissionStatus(...) and await
mutateHealthCenterSubmissionStatus() to after the upsertCookingProcessOrders
call (or perform the patch inside the success branch), and ensure any thrown
errors from upsert prevent the status update.

In `@user/src/components/Applications/Employees/Employees.tsx`:
- Line 16: The status prop on the Employees component is currently typed as a
plain string; change it to the stricter application status type used across the
app (e.g. APPLICATION_STATUS or ApplicationStatus) by importing that enum/type
and updating the prop/interface (e.g., the Props or EmployeesProps where
`status?: string` is declared) to `status?: APPLICATION_STATUS` (or the exact
exported name), and then adjust any usages inside Employees (rendering/filters)
to accept that enum type.
- Line 38: The inline comment for the isEdit prop is inaccurate: it says
"期限内または再提出待ちの場合に編集可能" but the code sets isEdit={!isDeadline} and does not
account for the resubmission state handled inside the Content component; either
update the comment to reflect that isEdit currently only checks isDeadline, or
change the expression passed to the isEdit prop to include the resubmission flag
used by Content (e.g., combine !isDeadline || isWaitingForResubmission or the
existing resubmission state name) so the prop and comment stay consistent (refer
to the isEdit prop, isDeadline variable, and the Content component's
resubmission logic).

In `@user/src/components/Applications/Employees/hooks.ts`:
- Line 378: The parameter currently typed as status?: string in
user/src/components/Applications/Employees/hooks.ts is too broad; change it to a
constrained type (e.g., an existing EmployeeStatus enum/union or create one like
'type EmployeeStatus = "active" | "inactive" | "terminated"') and replace
status?: string with status?: EmployeeStatus in the hook signature(s) that
accept status (search for functions/hooks in this file that declare a status
parameter), and update any callers or tests to use the specific values or cast
accordingly.
- Around line 518-524: The updateStatus('unapproved') call can reject and
currently has no error handling; wrap this call in a try/catch around the block
that checks if (status === 'waiting_resubmission') and on failure log the error
(use the existing logger or console.error) and surface user feedback (e.g., show
a toast or return an error response) so the rejection is handled gracefully
instead of causing an unhandled rejection; ensure you reference updateStatus and
the status check when implementing the try/catch and preserve existing flow on
success.

In `@user/src/components/Applications/FireEquipment/FireEquipment.tsx`:
- Line 11: The status prop on the FireEquipment component is currently typed too
broadly as status?: string; update the Props/interface for FireEquipment to use
the same stricter union type used elsewhere (for example replace string with the
established StatusType union like 'active'|'inactive'|'unknown' or the project's
shared Status enum/type), and update any imports to pull in the shared Status
type if it exists; ensure the prop declaration (status?: ...) and any places
that read or pass status in the FireEquipment component match the new type.
- Around line 35-46: Add a clarifying inline comment where the
FireEquipmentFormView is rendered with disableValidate (the branch guarded by
isDeadline && isResubmission) that explains that disableValidate intentionally
skips change-detection validation (not schema/Zod validation) to allow
resubmission even when no field values changed; reference the
FireEquipmentFormView prop disableValidate and the conditions isDeadline and
isResubmission, and add a matching comment in the similar branch that appears
later (the other condition around line 56) so future maintainers understand this
is intentional behavior.

In `@user/src/components/Applications/PurchaseLists/hooks.ts`:
- Around line 410-416: The current flow calls onSuccess() before awaiting
updateStatus('unapproved'), so if updateStatus fails the UI already left edit
mode and user sees a failure for a partially successful submit; change the flow
to perform the status patch first when status === 'waiting_resubmission' (await
updateStatus('unapproved')) and only call onSuccess() after that succeeds (or
alternatively call onSuccess() conditionally only when updateStatus resolves),
and keep reset(formData) after onSuccess(); also ensure the catch only treats
errors from the full sequence so failures in updateStatus are handled before UI
state changes.

In `@user/src/components/Applications/VenueMap/hooks.ts`:
- Around line 35-50: The updateStatus function can throw when no venue_map
submission exists and handleFormSubmitted calls it without catching errors; wrap
the call to updateStatus inside handleFormSubmitted with a try-catch (or
alternatively make updateStatus return a success/failure value instead of
throwing) and on failure log the error and surface a user-friendly message or
safe fallback; ensure you reference healthCenterSubmissionStatus,
patchHealthCenterSubmissionStatus and mutateHealthCenterSubmissionStatus so any
cleanup/mutateHealthCenterSubmissionStatus is still called on success or handled
appropriately on failure.
- Line 11: The status parameter on useVenueMapHooks is currently typed as
string; define a constrained union type (e.g., ApplicationStatus =
'waiting_resubmission' | 'approved' | 'unapproved') in a shared types file or
nearby and change the signature to useVenueMapHooks(groupId: number, status?:
ApplicationStatus) so only valid statuses are allowed; update any imports/usages
of useVenueMapHooks accordingly and run TypeScript checks to fix resulting type
errors.
- Line 33: The hook is being invoked twice—change the double-call pattern
useUpdateHealthCenterSubmissionStatus()() to a single hook call and destructure
its trigger; e.g. call const { trigger: patchHealthCenterSubmissionStatus } =
useUpdateHealthCenterSubmissionStatus();; locate
useUpdateHealthCenterSubmissionStatus (which wraps
useAuthenticatedPatchWithId(endpoint)) and replace any instances of the trailing
() invocation (also fix the same pattern for the analogous hooks in FoodProduct,
Employees, PurchaseLists, CookingProcessOrder, and FireEquipment) so the hook is
only called once and its trigger is used.

In `@user/src/components/Applications/VenueMap/VenueMap.tsx`:
- Line 11: The status prop on VenueMap (currently declared as status?: string)
should be narrowed to a specific union or enum to match hooks.ts; define a
VenueStatus union (e.g. 'open' | 'closed' | 'pending' etc.) or an exported enum
and change the prop signature in the VenueMapProps/interface from status?:
string to status?: VenueStatus, then update any usages and imports of VenueMap
and related hooks to use the same VenueStatus type so the types remain
consistent across VenueMap and hooks.ts.

In `@user/src/pages/home/index.tsx`:
- Line 351: The change made groupId to be possibly undefined (const groupId =
groupUserIdAndGroupCategoryId?.id ?? undefined), which breaks type expectations
for components that require groupId: number (VenueApplications, RentItems,
Power, PublicRelations, Employees, VenueMap, FoodProduct, PurchaseLists,
CookingProcessOrder, FireEquipment). Fix by either passing a numeric fallback
when rendering those components (use groupId || 0 in the JSX props where each
component is invoked) or change each component's prop type to accept number |
undefined and add internal guards in their props-handling logic; prefer the
former to match existing fallback usage (see renders around lines where groupId
is passed) to restore type compatibility without changing component internals.

---

Outside diff comments:
In `@user/src/components/Applications/FireEquipment/components/hooks.ts`:
- Around line 139-188: The resubmission status transition is only applied in
onSubmitFireEquipment, so when a user submits via the “火気不使用” path handled by
onSubmitUnregistered the health-center status can remain waiting_resubmission;
update onSubmitUnregistered to mirror onSubmitFireEquipment’s behavior by
calling updateStatus('unapproved') after the successful submit (after post/patch
and mutateFireEquipmentOrder/mutate equivalent and toast), guarded by if (status
=== 'waiting_resubmission'); use the existing updateStatus function to perform
the patch and subsequent mutateHealthCenterSubmissionStatus.

In `@user/src/components/Applications/FoodProduct/hooks.ts`:
- Around line 153-178: The current flow runs upsertFoodProducts and
mutateFoodProducts then calls updateStatus and if updateStatus fails the outer
catch treats the whole operation as failed; change this so
updateStatus('unapproved') is awaited inside its own try/catch (only when status
=== 'waiting_resubmission') and handle its error separately—e.g., log or show a
non-blocking warning toast instead of throwing—so success path
(setIsEditing(false), success toast) runs when the upsert/mutate completed;
locate the block around upsertFoodProducts, mutateFoodProducts, updateStatus,
and status === 'waiting_resubmission' to implement the isolated try/catch.

In `@user/src/pages/home/index.tsx`:
- Around line 367-388: There is an inconsistent fallback for groupId: some
places pass groupId || 0 while earlier code allows groupId to be undefined; pick
one approach and make it consistent — either (A) enforce a 0 default at the
source (set the parent variable to use nullish coalescing, e.g. groupId =
incomingGroupId ?? 0) so all children (ViceRepresentative, GroupCategoryContent
and any other consumers using the groupId prop) can safely rely on a numeric id,
or (B) remove the inline fallbacks (drop the "|| 0" in the props for
ViceRepresentative and GroupCategoryContent and anywhere else) and update those
child components (their prop types/handlers) to accept undefined and handle that
state; update the symbol(s) ViceRepresentative, GroupCategoryContent and any
mutate* callers accordingly so the behavior is uniform.
- Around line 162-339: The VenueMap, FoodProduct, and FireEquipment components
accept a status?: string prop used to enable resubmission, but in the
GOODS_SALES, RESEARCH_LAB, EXHIBITION, and COMMITTEE branches you are not
passing status (only FOOD_SALES does), disabling resubmission; fix this by
deriving the submission status in those branches the same way you do in the
FOOD_SALES branch and pass it into the components as status={...} (update the
VenueMap, FoodProduct, and FireEquipment JSX in the GOODS_SALES, RESEARCH_LAB,
EXHIBITION, and COMMITTEE branches to include the status prop, using the same
status source logic used for FOOD_SALES so resubmission logic activates where
appropriate).

---

Nitpick comments:
In `@user/src/api/healthCenterSubmissionStatusApi.ts`:
- Around line 43-47: The status field in HealthCenterSubmissionStatusResponse
should not be a raw string; define a typed union (e.g., export a
SubmissionStatus type with the allowed literals such as "waiting_resubmission"
and the other known status values) and replace status: string with status:
SubmissionStatus; update any related usages to import/use SubmissionStatus so
downstream code has strict literal typing.

In `@user/src/components/Applications/Employees/hooks.ts`:
- Line 401: The updateStatus function currently uses the magic string
'unapproved'; replace this literal with a shared constant or enum (e.g.,
STATUS_UNAPPROVED or an EmployeeStatus enum) to match the pattern used in
VenueMap/hooks.ts. Update the function signature and any call sites that pass or
compare 'unapproved' to import and use the new constant/enum, and ensure
TypeScript types are adjusted (union or enum type) so updateStatus accepts the
constant/enum value instead of the raw string.

In `@user/src/components/Applications/VenueMap/hooks.ts`:
- Line 35: The updateStatus function currently uses the literal 'unapproved' as
both a type and value; define a shared constant or enum (e.g., VenueStatus with
UNAPPROVED) and replace the literal in the updateStatus signature and all
callers where 'unapproved' is passed; update any related type annotations or
imports to reference the new VenueStatus constant/enum so callers use
VenueStatus.UNAPPROVED instead of the magic string.

In `@user/src/pages/home/index.tsx`:
- Around line 82-99: Multiple .find() calls over healthCenterSubmissionStatus
(used to create employeeSubmission, foodProductsSubmission,
purchaseListsSubmission, venueMapSubmission, cookingProcessOrderSubmission,
fireEquipmentSubmission) cause repeated iteration; replace them with a single
pass that builds a lookup (e.g., reduce into an object or a Map keyed by
applicationType) and then reference lookup['employee'], lookup['food_product'],
etc.; update the variables to pull from that lookup (employeeSubmission =
lookup['employee'], etc.) so you iterate the array only once.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9cb70e0f-849d-4a15-93eb-ec8e7d552389

📥 Commits

Reviewing files that changed from the base of the PR and between 7205f52 and 1d8a939.

⛔ Files ignored due to path filters (1)
  • admin_view/nuxt-project/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (26)
  • admin_view/nuxt-project/package.json
  • user/public/locales/en/common.json
  • user/public/locales/ja/common.json
  • user/src/api/checkAllRegisteredApi.ts
  • user/src/api/healthCenterSubmissionStatusApi.ts
  • user/src/components/AccordionMenu/AccordionMenu.tsx
  • user/src/components/Applications/CookingProcessOrder/CookingProcessOrder.tsx
  • user/src/components/Applications/CookingProcessOrder/hooks.ts
  • user/src/components/Applications/Employees/Employees.tsx
  • user/src/components/Applications/Employees/hooks.ts
  • user/src/components/Applications/FireEquipment/FireEquipment.tsx
  • user/src/components/Applications/FireEquipment/components/FireEquipmentFormView.tsx
  • user/src/components/Applications/FireEquipment/components/hooks.ts
  • user/src/components/Applications/FireEquipment/hooks.ts
  • user/src/components/Applications/FoodProduct/FoodProduct.tsx
  • user/src/components/Applications/FoodProduct/hooks.ts
  • user/src/components/Applications/PurchaseLists/PurchaseLists.tsx
  • user/src/components/Applications/PurchaseLists/hooks.ts
  • user/src/components/Applications/VenueMap/VenueMap.tsx
  • user/src/components/Applications/VenueMap/hooks.ts
  • user/src/components/Status/Status.tsx
  • user/src/components/Status/hooks.ts
  • user/src/pages/home/index.tsx
  • user/src/styles/globals.css
  • user/src/utils/constants.ts
  • user/tailwind.config.ts
💤 Files with no reviewable changes (1)
  • admin_view/nuxt-project/package.json

Comment on lines +66 to +68
const endpoint = groupId
? `${API_ENDPOINTS.HEALTH_CENTER_SUBMISSION_STATUS}/${groupId}`
: null;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Use a nullish check for groupId when building the endpoint.

At Line 66, the truthy check (groupId ? ...) skips fetch when groupId is 0. Use groupId != null for consistent behavior.

💡 Suggested fix
-  const endpoint = groupId
+  const endpoint = groupId != null
     ? `${API_ENDPOINTS.HEALTH_CENTER_SUBMISSION_STATUS}/${groupId}`
     : null;
📝 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
const endpoint = groupId
? `${API_ENDPOINTS.HEALTH_CENTER_SUBMISSION_STATUS}/${groupId}`
: null;
const endpoint = groupId != null
? `${API_ENDPOINTS.HEALTH_CENTER_SUBMISSION_STATUS}/${groupId}`
: null;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/api/healthCenterSubmissionStatusApi.ts` around lines 66 - 68, The
endpoint construction uses a truthy check on groupId which incorrectly treats 0
as absent; update the conditional in the endpoint assignment to use a nullish
check (e.g., groupId != null) so that values like 0 are allowed, keeping the
reference to API_ENDPOINTS.HEALTH_CENTER_SUBMISSION_STATUS and the endpoint
constant (endpoint) and groupId identifier intact.

Comment on lines +151 to +166
const updateStatus = async (status: 'unapproved') => {
const cookingProcessOrderSubmission = healthCenterSubmissionStatus.find(
(submission) => submission.applicationType === 'cooking_process_order'
);

if (!cookingProcessOrderSubmission?.id) {
throw new Error('Cooking process order submission status id not found');
}

await patchHealthCenterSubmissionStatus({
id: cookingProcessOrderSubmission.id,
body: { status },
});

await mutateHealthCenterSubmissionStatus();
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Update the submission status only after the save succeeds.

Right now the resubmission status is patched before upsertCookingProcessOrders. If the upsert fails afterward, this application leaves waiting_resubmission even though the user’s changes were never persisted.

Suggested fix
-      // 再提出完了時
-      if (status === 'waiting_resubmission') {
-        // status更新処理
-        await updateStatus('unapproved');
-      }
-
       await upsertCookingProcessOrders({
         body: { cooking_process_orders: payload },
       });
+
+      if (status === 'waiting_resubmission') {
+        await updateStatus('unapproved');
+      }

Also applies to: 183-191

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/components/Applications/CookingProcessOrder/hooks.ts` around lines
151 - 166, The status patch is performed before persisting data, so if
upsertCookingProcessOrders fails the submission stays in waiting_resubmission;
change the order so patchHealthCenterSubmissionStatus (and
mutateHealthCenterSubmissionStatus) is called only after await
upsertCookingProcessOrders completes successfully. Locate updateStatus and the
code path that calls upsertCookingProcessOrders (and the similar block around
lines 183-191), move the await patchHealthCenterSubmissionStatus(...) and await
mutateHealthCenterSubmissionStatus() to after the upsertCookingProcessOrders
call (or perform the patch inside the success branch), and ensure any thrown
errors from upsert prevent the status update.

isRegistered?: boolean; // 既に登録済みかどうか
groupId: number; // 対象のグループID
mutateCheckAllRegisteredGroups: () => void;
status?: string; // 申請のステータス(APPLICATION_STATUSの値)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use a more specific type for the status prop.

Consistent with other components, use a stricter type for status.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/components/Applications/Employees/Employees.tsx` at line 16, The
status prop on the Employees component is currently typed as a plain string;
change it to the stricter application status type used across the app (e.g.
APPLICATION_STATUS or ApplicationStatus) by importing that enum/type and
updating the prop/interface (e.g., the Props or EmployeesProps where `status?:
string` is declared) to `status?: APPLICATION_STATUS` (or the exact exported
name), and then adjust any usages inside Employees (rendering/filters) to accept
that enum type.

<AccordionMenu
title={employeesApplicationHook.texts.title}
isEdit={!isDeadline} // 期限内(isDeadline=false)の場合のみ編集可能
isEdit={!isDeadline} // 期限内または再提出待ちの場合に編集可能
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Fix inconsistent comment.

The comment states "期限内または再提出待ちの場合に編集可能" (editable during deadline or resubmission), but isEdit={!isDeadline} only checks the deadline, not the resubmission status. The actual resubmission logic is handled inside Content at lines 109-113 and 126-131.

📝 Update the comment
    <AccordionMenu
      title={employeesApplicationHook.texts.title}
-     isEdit={!isDeadline} // 期限内または再提出待ちの場合に編集可能
+     isEdit={!isDeadline} // 期限内の場合に編集アイコン表示
      isExist={isRegistered} // 登録済みの場合に表示
      required={true} // 必須項目として表示
      status={status} // 申請のステータスを渡す
    >

Or update the logic to match the comment:

-     isEdit={!isDeadline} // 期限内または再提出待ちの場合に編集可能
+     isEdit={!isDeadline || status === 'waiting_resubmission'} // 期限内または再提出待ちの場合に編集可能
📝 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
isEdit={!isDeadline} // 期限内または再提出待ちの場合に編集可能
isEdit={!isDeadline} // 期限内の場合に編集アイコン表示
Suggested change
isEdit={!isDeadline} // 期限内または再提出待ちの場合に編集可能
isEdit={!isDeadline || status === 'waiting_resubmission'} // 期限内または再提出待ちの場合に編集可能
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/components/Applications/Employees/Employees.tsx` at line 38, The
inline comment for the isEdit prop is inaccurate: it says "期限内または再提出待ちの場合に編集可能"
but the code sets isEdit={!isDeadline} and does not account for the resubmission
state handled inside the Content component; either update the comment to reflect
that isEdit currently only checks isDeadline, or change the expression passed to
the isEdit prop to include the resubmission flag used by Content (e.g., combine
!isDeadline || isWaitingForResubmission or the existing resubmission state name)
so the prop and comment stay consistent (refer to the isEdit prop, isDeadline
variable, and the Content component's resubmission logic).

isDeadline?: boolean,
mutateCheckAllRegisteredGroups?: () => void
mutateCheckAllRegisteredGroups?: () => void,
status?: string
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use a more specific type for the status parameter.

Same issue as in other hooks — status?: string should be constrained to valid status values.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/components/Applications/Employees/hooks.ts` at line 378, The
parameter currently typed as status?: string in
user/src/components/Applications/Employees/hooks.ts is too broad; change it to a
constrained type (e.g., an existing EmployeeStatus enum/union or create one like
'type EmployeeStatus = "active" | "inactive" | "terminated"') and replace
status?: string with status?: EmployeeStatus in the hook signature(s) that
accept status (search for functions/hooks in this file that declare a status
parameter), and update any callers or tests to use the specific values or cast
accordingly.

import { venueMapLabels } from '../label';

export const useVenueMapHooks = (groupId: number) => {
export const useVenueMapHooks = (groupId: number, status?: string) => {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use a more specific type for the status parameter.

The status parameter is typed as string, but it should be constrained to valid application status values. This would prevent invalid status strings from being passed and improve type safety.

📐 Suggested improvement
-export const useVenueMapHooks = (groupId: number, status?: string) => {
+export const useVenueMapHooks = (groupId: number, status?: 'waiting_resubmission' | 'approved' | 'unapproved') => {

Or better yet, define and import a type:

// In a shared types file
export type ApplicationStatus = 'waiting_resubmission' | 'approved' | 'unapproved';

// In this file
export const useVenueMapHooks = (groupId: number, status?: ApplicationStatus) => {
📝 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
export const useVenueMapHooks = (groupId: number, status?: string) => {
export const useVenueMapHooks = (groupId: number, status?: 'waiting_resubmission' | 'approved' | 'unapproved') => {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/components/Applications/VenueMap/hooks.ts` at line 11, The status
parameter on useVenueMapHooks is currently typed as string; define a constrained
union type (e.g., ApplicationStatus = 'waiting_resubmission' | 'approved' |
'unapproved') in a shared types file or nearby and change the signature to
useVenueMapHooks(groupId: number, status?: ApplicationStatus) so only valid
statuses are allowed; update any imports/usages of useVenueMapHooks accordingly
and run TypeScript checks to fix resulting type errors.

const { healthCenterSubmissionStatus, mutateHealthCenterSubmissionStatus } =
useGetHealthCenterSubmissionStatus(groupId);
const { trigger: patchHealthCenterSubmissionStatus } =
useUpdateHealthCenterSubmissionStatus()();
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check the signature of useUpdateHealthCenterSubmissionStatus
ast-grep --pattern 'export const useUpdateHealthCenterSubmissionStatus = $$$'

# Also check other similar update hooks for comparison
rg -nP 'useUpdate\w+\(\)\(\)' --type=ts -C2

Repository: NUTFes/group-manager-2

Length of output: 4687


🏁 Script executed:

# Find the definition of useAuthenticatedPatchWithId
rg -n 'export.*useAuthenticatedPatchWithId|const useAuthenticatedPatchWithId' --type=ts -A5

Repository: NUTFes/group-manager-2

Length of output: 505


🏁 Script executed:

# Find createMutationHookWithId definition
rg -n 'function createMutationHookWithId|const createMutationHookWithId|export.*createMutationHookWithId' --type=ts -A10

Repository: NUTFes/group-manager-2

Length of output: 2124


🏁 Script executed:

# Get full definition of useUpdateHealthCenterSubmissionStatus
rg -n 'export const useUpdateHealthCenterSubmissionStatus' --type=ts -A5

Repository: NUTFes/group-manager-2

Length of output: 537


Remove the double invocation pattern — it incorrectly calls the hook twice.

useUpdateHealthCenterSubmissionStatus() already returns the hook from useAuthenticatedPatchWithId(endpoint). The second () attempts to invoke the hook itself, which is incorrect. Use:

const { trigger: patchHealthCenterSubmissionStatus } = useUpdateHealthCenterSubmissionStatus();

This same pattern appears in at least 5 other files (FoodProduct, Employees, PurchaseLists, CookingProcessOrder, FireEquipment) and should be corrected across the codebase.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/components/Applications/VenueMap/hooks.ts` at line 33, The hook is
being invoked twice—change the double-call pattern
useUpdateHealthCenterSubmissionStatus()() to a single hook call and destructure
its trigger; e.g. call const { trigger: patchHealthCenterSubmissionStatus } =
useUpdateHealthCenterSubmissionStatus();; locate
useUpdateHealthCenterSubmissionStatus (which wraps
useAuthenticatedPatchWithId(endpoint)) and replace any instances of the trailing
() invocation (also fix the same pattern for the analogous hooks in FoodProduct,
Employees, PurchaseLists, CookingProcessOrder, and FireEquipment) so the hook is
only called once and its trigger is used.

Comment on lines +35 to +50
const updateStatus = async (status: 'unapproved') => {
const venueMapSubmission = healthCenterSubmissionStatus.find(
(submission) => submission.applicationType === 'venue_map'
);

if (!venueMapSubmission?.id) {
throw new Error('Venue map submission status id not found');
}

await patchHealthCenterSubmissionStatus({
id: venueMapSubmission.id,
body: { status },
});

await mutateHealthCenterSubmissionStatus();
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Add error handling for the status update flow.

The updateStatus function throws an error when the submission is not found (line 41), and is called without a try-catch in handleFormSubmitted (line 56). This will cause unhandled promise rejections if the submission record is missing.

🛡️ Add error handling
  const handleFormSubmitted = async () => {
    if (status === 'waiting_resubmission') {
-     // status更新処理
-     await updateStatus('unapproved');
+     try {
+       await updateStatus('unapproved');
+     } catch (error) {
+       console.error('Failed to update submission status:', error);
+       // Consider showing a user-facing error message
+     }
    }

    setIsEditing(false);
  };
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/components/Applications/VenueMap/hooks.ts` around lines 35 - 50, The
updateStatus function can throw when no venue_map submission exists and
handleFormSubmitted calls it without catching errors; wrap the call to
updateStatus inside handleFormSubmitted with a try-catch (or alternatively make
updateStatus return a success/failure value instead of throwing) and on failure
log the error and surface a user-friendly message or safe fallback; ensure you
reference healthCenterSubmissionStatus, patchHealthCenterSubmissionStatus and
mutateHealthCenterSubmissionStatus so any
cleanup/mutateHealthCenterSubmissionStatus is still called on success or handled
appropriately on failure.

groupId: number;
isDeadline?: boolean;
isRegistered?: boolean;
status?: string;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Use a more specific type for the status prop.

Same issue as in hooks.ts — the status prop should use a union type or enum rather than the broad string type.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/components/Applications/VenueMap/VenueMap.tsx` at line 11, The
status prop on VenueMap (currently declared as status?: string) should be
narrowed to a specific union or enum to match hooks.ts; define a VenueStatus
union (e.g. 'open' | 'closed' | 'pending' etc.) or an exported enum and change
the prop signature in the VenueMapProps/interface from status?: string to
status?: VenueStatus, then update any usages and imports of VenueMap and related
hooks to use the same VenueStatus type so the types remain consistent across
VenueMap and hooks.ts.

isLoading: isLoadingGroupByUserId,
} = useGetGroupByUserId(userId);
const groupId = groupUserIdAndGroupCategoryId?.id ?? 0;
const groupId = groupUserIdAndGroupCategoryId?.id ?? undefined;
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check if useGetCheckAllRegisteredGroups handles undefined groupId
ast-grep --pattern 'export const useGetCheckAllRegisteredGroups = ($$$) => { $$$ }'

# Check if useGetHealthCenterSubmissionStatus handles undefined groupId
ast-grep --pattern 'export const useGetHealthCenterSubmissionStatus = ($$$) => { $$$ }'

# Find all places where groupId is used as a required number
rg -nP 'groupId:\s*number[^?|]' --type=ts user/src/components/Applications/ -C2

Repository: NUTFes/group-manager-2

Length of output: 34062


🏁 Script executed:

# First, get the file and check around line 351
wc -l user/src/pages/home/index.tsx

Repository: NUTFes/group-manager-2

Length of output: 100


🏁 Script executed:

# View the context around line 351 to see how groupId is used after the assignment
sed -n '345,400p' user/src/pages/home/index.tsx

Repository: NUTFes/group-manager-2

Length of output: 2235


🏁 Script executed:

# Check what components receive groupId in home/index.tsx
rg -n 'groupId=' user/src/pages/home/index.tsx -A2 -B2

Repository: NUTFes/group-manager-2

Length of output: 8837


🏁 Script executed:

# Check the exact type definitions for components that receive groupId without || 0 fallback
rg -n 'type VenueApplicationProps|type RentItemsProps|type PowerProps|type PublicRelationsProps|type VenueMapProps|type FoodProductProps|type PurchaseListsProps|type CookingProcessOrderProps|type FireEquipmentProps|type EmployeesProps' user/src/components/Applications/ -A5 | head -100

Repository: NUTFes/group-manager-2

Length of output: 5514


🏁 Script executed:

# Check the full context around lines 106-158 to see if groupId is guarded
sed -n '95,160p' user/src/pages/home/index.tsx

Repository: NUTFes/group-manager-2

Length of output: 2493


🏁 Script executed:

# Check if there's any conditional check that guards the rendering of these components
sed -n '80,110p' user/src/pages/home/index.tsx

Repository: NUTFes/group-manager-2

Length of output: 1314


🏁 Script executed:

# Check what happens when groupUserIdAndGroupCategoryId is null/undefined
sed -n '348,365p' user/src/pages/home/index.tsx

Repository: NUTFes/group-manager-2

Length of output: 920


Pass groupId || 0 to components requiring number type, or update component props to accept number | undefined.

Changing from ?? 0 to ?? undefined at line 351 makes groupId potentially undefined. However, components at lines 106–158 (VenueApplications, RentItems, Power, PublicRelations, Employees, VenueMap, FoodProduct, PurchaseLists, CookingProcessOrder, FireEquipment) receive groupId directly without fallback, but all require groupId: number per their type definitions. This creates a type mismatch that will cause pnpm run type-check to fail, violating the Next.js coding guidelines.

Either:

  • Apply the || 0 fallback pattern already used at lines 367, 378, 388 to all component passes, or
  • Update component prop types to accept number | undefined and add internal guards
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@user/src/pages/home/index.tsx` at line 351, The change made groupId to be
possibly undefined (const groupId = groupUserIdAndGroupCategoryId?.id ??
undefined), which breaks type expectations for components that require groupId:
number (VenueApplications, RentItems, Power, PublicRelations, Employees,
VenueMap, FoodProduct, PurchaseLists, CookingProcessOrder, FireEquipment). Fix
by either passing a numeric fallback when rendering those components (use
groupId || 0 in the JSX props where each component is invoked) or change each
component's prop type to accept number | undefined and add internal guards in
their props-handling logic; prefer the former to match existing fallback usage
(see renders around lines where groupId is passed) to restore type compatibility
without changing component internals.

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.

[feat] user画面再提出機能の実装

3 participants