Skip to content

[CCI-4] 일대다 면접 리스트 조회, 상세 조회, 면접 신청 기능 추가 및 번호로 로그인하기 기능 추가#3

Merged
jpark0506 merged 3 commits intomainfrom
feat/CCI-4
Jun 2, 2025
Merged

[CCI-4] 일대다 면접 리스트 조회, 상세 조회, 면접 신청 기능 추가 및 번호로 로그인하기 기능 추가#3
jpark0506 merged 3 commits intomainfrom
feat/CCI-4

Conversation

@jpark0506
Copy link
Contributor

@jpark0506 jpark0506 commented Jun 2, 2025

Summary by CodeRabbit

  • New Features

    • Added dynamic fetching and display of group interview posts, details, and participation forms, replacing previous static data.
    • Enabled users to join group interviews, select resumes and cover letters, and view participant lists with real-time data.
    • Introduced prompts for member ID input during temporary login.
    • Added new interview management API functions for updating options, retrieving group interview cards/details, and starting interviews.
  • Bug Fixes

    • Improved error handling and validation for login, form submissions, and data loading states.
  • Refactor

    • Updated interview-related pages to use new API endpoints and data structures for consistency and reliability.
    • Enhanced date selection logic to update interview start type alongside scheduled date.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jun 2, 2025

Walkthrough

This update introduces new API endpoints and TypeScript interfaces for group interview management, including updating interview options, retrieving group interview cards and details, and starting interviews. Several React components are refactored to fetch and display live data from these new APIs, replacing static mock data and enhancing user interaction and state management.

Changes

File(s) Change Summary
api/interview.ts Added API functions: updateInterviewOption, getGroupInterviewCards, getGroupInterviewDetail, and startInterview for group interview management.
api/types/interview-types.ts Introduced new TypeScript interfaces for interview option updates, group interview cards/details, interview start responses, and related DTOs.
app/login/page.tsx Changed temporary login to prompt for member ID, validate input, and handle login/redirect accordingly.
app/workspace/interview/group/community/[id]/join/page.tsx
app/workspace/interview/group/community/[id]/page.tsx
app/workspace/interview/group/community/page.tsx
Refactored components to fetch group interview data using new API endpoints and React Query; updated UI and logic to use live data, manage loading/error states, and enhance user session awareness and conditional rendering.
components/interview/steps/Step4Group.tsx Modified calendar date selection handler to update form state with both startType and scheduledDate when a valid date is selected.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant UI
    participant API
    participant Server

    User->>UI: Navigates to group interview page
    UI->>API: getGroupInterviewCards()
    API->>Server: Fetch group interview cards
    Server-->>API: Returns list of group interviews
    API-->>UI: Returns data
    UI->>User: Displays interview cards

    User->>UI: Selects interview for details
    UI->>API: getGroupInterviewDetail(interviewId)
    API->>Server: Fetch interview detail
    Server-->>API: Returns interview detail
    API-->>UI: Returns data
    UI->>User: Displays interview detail

    User->>UI: Joins interview (selects resume/cover letter)
    UI->>API: updateInterviewOption(interviewId, memberId, data)
    API->>Server: Update interview option
    Server-->>API: Returns update status
    API-->>UI: Returns response
    UI->>User: Shows confirmation
Loading

Possibly related PRs

Suggested labels

enhancement

Poem

In the meadow of code, new interviews bloom,
With APIs fresh and data that zooms.
No more mock carrots, just live, crunchy bites,
Rabbits fetch details and join with delight.
Hop to the future, group interviews in sight—
Every bunny’s ready for a data-driven night! 🥕✨

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • 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 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.

@jpark0506 jpark0506 self-assigned this Jun 2, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🔭 Outside diff range comments (1)
app/workspace/interview/group/community/[id]/page.tsx (1)

3-20: ⚠️ Potential issue

Avoid experimental use() in a client component & simplify params handling

use() is still experimental and, in Next .js 14, is only available in server components.
Because this file is marked "use client", hydration will fail in browsers that do not bundle the experimental hook.
You can safely treat params synchronously – it is never a Promise on the client.

-import { useState, useEffect } from "react"
+import { useState, useEffect } from "react"-import { use as usePromise } from "react"-export default function InterviewPostDetailPage({ params }: { params: Promise<{ id: string }> }) {
-  const { id: postId } = usePromise(params)
+export default function InterviewPostDetailPage({ params }: { params: { id: string } }) {
+  const { id: postId } = params

This removes a hard runtime dependency on an unstable API and aligns with the official Next .js route‐handler signature.

🧹 Nitpick comments (6)
app/login/page.tsx (1)

44-54: Consider improving the temporary login UX.

While the current window.prompt() implementation works for testing purposes, consider these improvements for better user experience:

  • Replace window.prompt() with a proper modal dialog component
  • Add better input validation feedback
  • Consider persisting the login state properly

The current validation logic is solid and handles edge cases well.

Here's a potential improvement using a proper dialog:

-              <Button variant="outline" className="w-full" onClick={() => {
-                const input = window.prompt('로그인할 멤버 ID를 입력하세요')
-                if (!input) return
-                const id = Number(input)
-                if (isNaN(id) || id <= 0) {
-                  alert('올바른 숫자 ID를 입력하세요')
-                  return
-                }
-                login(id)
-                window.location.href = "/workspace"
-              }}>
+              <Button variant="outline" className="w-full" onClick={handleTempLogin}>
                 임시 로그인
               </Button>

And add a proper dialog component for better UX.

api/types/interview-types.ts (1)

236-236: Address the TODO comment for better type safety.

The comment indicates that coverLetterDTO needs proper typing instead of any. This should be addressed to maintain type safety throughout the application.

Consider creating a proper interface for the cover letter DTO:

export interface CoverLetterSimpleDTO {
  coverLetterId?: number;
  title?: string;
  content?: string;
  // Add other relevant fields based on your cover letter data structure
}

Then update the ParticipantDTO:

export interface ParticipantDTO {
  memberInterviewId?: number;
  resumeDTO?: ResumeSimpleDTO;
-  coverLetterDTO?: any; // CoverletterDetailDTO 등 실제 타입에 맞게 수정 필요
+  coverLetterDTO?: CoverLetterSimpleDTO;
}
app/workspace/interview/group/community/[id]/page.tsx (2)

86-105: Hard-coded “추천 모집글” mock should be moved to live data or feature flag

The component now relies on live data everywhere except recommendedPosts, which is still static.
Mixing mock and production data can confuse users once the backend goes live. Either:

  1. Replace this with an API call (preferred), or
  2. Hide this block behind a feature flag until the endpoint exists.

No action required if this is intentional for early demos.


106-114: Surfacing raw error messages may leak implementation details

error.message can contain internal server traces. Consider showing a generic message and logging the detailed error only in non-production builds.

-let msg = '데이터 없음'
+let msg = '데이터를 불러오지 못했습니다.'-else if (error instanceof Error) msg = error.message
+else if (process.env.NODE_ENV !== 'production' && error instanceof Error) {
+  msg = error.message
+}
app/workspace/interview/group/community/[id]/join/page.tsx (2)

49-53: isAlreadyApplied may evaluate before data is ready

When interviewLoading is true, post is undefined, so some() will throw.
Although ?. protects the call, the expression still runs each render.
Move the computation into a useMemo that depends on post to avoid unnecessary evaluations:

const isAlreadyApplied = useMemo(
  () => post?.groupInterviewParticipants?.some(p => p.memberId === memberId) ?? false,
  [post, memberId]
)

55-72: API error surfaces internal message & misses type-guard

onError assumes err has .message. Guard explicitly and avoid leaking internal details in production:

-onError: (err: any) => {
-  alert(err?.message || '면접 참여 신청에 실패했습니다.')
+onError: (err) => {
+  const msg =
+    err instanceof Error && process.env.NODE_ENV !== 'production'
+      ? err.message
+      : '면접 참여 신청에 실패했습니다.'
+  alert(msg)
 },
📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between c651825 and d86a621.

📒 Files selected for processing (6)
  • api/interview.ts (2 hunks)
  • api/types/interview-types.ts (1 hunks)
  • app/login/page.tsx (1 hunks)
  • app/workspace/interview/group/community/[id]/join/page.tsx (7 hunks)
  • app/workspace/interview/group/community/[id]/page.tsx (8 hunks)
  • app/workspace/interview/group/community/page.tsx (4 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (2)
api/interview.ts (2)
api/types/interview-types.ts (5)
  • InterviewOptionUpdateDTO (109-121)
  • ApiResponseInterviewOptionUpdateResponseDTO (123-128)
  • ApiResponseListInterviewGroupCardDTO (147-152)
  • ApiResponseGroupInterviewDetailDTO (166-171)
  • ApiResponseInterviewStartResponseDTO (195-200)
utils/fetch/fetch.ts (1)
  • serverFetch (135-135)
app/workspace/interview/group/community/[id]/join/page.tsx (7)
components/member-session-context.tsx (1)
  • useMemberSession (39-43)
api/interview.ts (2)
  • getGroupInterviewDetail (57-61)
  • createMemberInterview (27-35)
lib/api.ts (1)
  • post (1-15)
api/resume.ts (1)
  • getResumeList (33-35)
api/coverletter.ts (1)
  • findMyCoverletter (25-29)
components/ui/select.tsx (1)
  • SelectItem (156-156)
components/ui/button.tsx (1)
  • Button (56-56)
🔇 Additional comments (14)
api/interview.ts (3)

11-16: Well-structured imports for new functionality.

The new TypeScript interface imports are properly organized and support the new API functions effectively.


37-47: Excellent API function implementation.

The updateInterviewOption function follows established patterns with:

  • Proper TypeScript generics for type safety
  • Appropriate PATCH method for updates
  • Correct parameter structure including memberId
  • Consistent error handling

49-68: Clean and consistent API functions for group interview features.

The three new GET endpoints (getGroupInterviewCards, getGroupInterviewDetail, startInterview) are well-implemented with:

  • Proper TypeScript typing
  • RESTful URL patterns
  • Consistent return types
  • Clear function names that match their purpose
app/workspace/interview/group/community/page.tsx (6)

13-14: Proper API integration with React Query.

The imports for the new API function and React Query are correctly added to support the data-driven refactoring.


17-23: Excellent React Query implementation.

The query setup is well-structured with:

  • Descriptive query key
  • Proper API function integration
  • Destructured response for easy access to loading and error states

30-46: Well-updated filtering logic for new data structure.

The filtering logic has been properly adapted to work with the new API data structure:

  • Date filtering uses startedAt field appropriately
  • Type filtering maps correctly to interviewType enum values
  • Search functionality covers both name and jobName fields
  • Safe navigation with optional chaining

75-84: Robust date formatting with proper null handling.

The formatDate function properly handles undefined/null values and provides consistent formatting for the Korean locale.


167-171: Proper loading and error state handling.

The UI appropriately displays loading states and error messages, providing good user feedback during API calls.


207-212: Improved button implementation with proper Link component.

The button correctly uses the asChild prop with nested Link component for better semantic HTML and routing behavior.

api/types/interview-types.ts (3)

109-144: Well-structured interview option types.

The InterviewOptionUpdateDTO and related response types are properly defined with:

  • Consistent voice type enums
  • Appropriate field types
  • Proper optional field markings for response DTOs

147-192: Comprehensive group interview type definitions.

The group interview interfaces are well-designed with:

  • Clear separation between list and detail views
  • Proper participant data structure
  • Consistent field naming and types
  • Appropriate use of optional fields

195-237: Complete interview start response types.

The interview start functionality is properly typed with comprehensive DTOs covering all necessary data structures.

app/workspace/interview/group/community/[id]/page.tsx (1)

28-31: isHost logic compares different identifiers

memberId (numeric) is being compared to post.hostName (string).
Unless the backend sends the host’s member id in hostName, this check will always be false, preventing hosts from accessing host-only controls.

Please compare against an id field (hostId, hostMemberId, …) returned by the API:

-const isHost = !!(
-  memberId && post && post.hostName && String(memberId) === post.hostName
-)
+const isHost = memberId !== undefined && post?.hostMemberId === memberId

If the DTO does not yet expose such an id, consider updating it.

app/workspace/interview/group/community/[id]/join/page.tsx (1)

74-86: Host check uses hostName instead of host id

Same mismatch as in the detail page; this could wrongly block/allow applications.

-if (memberId && post.hostName && String(memberId) === post.hostName) {
+if (memberId !== undefined && post?.hostMemberId === memberId) {

Verify the correct identifier is available in the DTO.

Comment on lines +3 to +19
import { useState, use as usePromise } from "react"
import Link from "next/link"
import { Button } from "@/components/ui/button"
import { ArrowLeft, ArrowRight, Info } from "lucide-react"
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Label } from "@/components/ui/label"
import { useQuery, useMutation } from '@tanstack/react-query'
import { getGroupInterviewDetail } from '@/api/interview'
import { getResumeList } from '@/api/resume'
import { findMyCoverletter } from '@/api/coverletter'
import { createMemberInterview } from '@/api/interview'
import { useMemberSession } from '@/components/member-session-context'

export default function JoinGroupInterviewPage({ params }: { params: { id: string } }) {
const postId = params.id
export default function JoinGroupInterviewPage({ params }: { params: Promise<{ id: string }> }) {
const { id: postId } = usePromise(params)
const { memberId } = useMemberSession()
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove Promise-based params & experimental use() here as well

Same reasoning as in the detail page: this is a client component and receives params synchronously.

-import { useState, use as usePromise } from "react"
+import { useState } from "react"-export default function JoinGroupInterviewPage({ params }: { params: Promise<{ id: string }> }) {
-  const { id: postId } = usePromise(params)
+export default function JoinGroupInterviewPage({ params }: { params: { id: string } }) {
+  const { id: postId } = params

This prevents relying on an unstable React API and simplifies the component.

📝 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
import { useState, use as usePromise } from "react"
import Link from "next/link"
import { Button } from "@/components/ui/button"
import { ArrowLeft, ArrowRight, Info } from "lucide-react"
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Label } from "@/components/ui/label"
import { useQuery, useMutation } from '@tanstack/react-query'
import { getGroupInterviewDetail } from '@/api/interview'
import { getResumeList } from '@/api/resume'
import { findMyCoverletter } from '@/api/coverletter'
import { createMemberInterview } from '@/api/interview'
import { useMemberSession } from '@/components/member-session-context'
export default function JoinGroupInterviewPage({ params }: { params: { id: string } }) {
const postId = params.id
export default function JoinGroupInterviewPage({ params }: { params: Promise<{ id: string }> }) {
const { id: postId } = usePromise(params)
const { memberId } = useMemberSession()
import { useState } from "react"
import Link from "next/link"
import { Button } from "@/components/ui/button"
import { ArrowLeft, ArrowRight, Info } from "lucide-react"
import { Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { Label } from "@/components/ui/label"
import { useQuery, useMutation } from '@tanstack/react-query'
import { getGroupInterviewDetail } from '@/api/interview'
import { getResumeList } from '@/api/resume'
import { findMyCoverletter } from '@/api/coverletter'
import { createMemberInterview } from '@/api/interview'
import { useMemberSession } from '@/components/member-session-context'
export default function JoinGroupInterviewPage({ params }: { params: { id: string } }) {
const { id: postId } = params
const { memberId } = useMemberSession()
// ...
}
🤖 Prompt for AI Agents
In app/workspace/interview/group/community/[id]/join/page.tsx around lines 3 to
19, the component currently types the params prop as a Promise and uses the
experimental React use() hook to unwrap it. Since this is a client component and
params are passed synchronously, remove the Promise type from params and
eliminate the use() call. Instead, access params.id directly without awaiting or
unwrapping, simplifying the component and avoiding unstable React APIs.

@jpark0506 jpark0506 merged commit 840e66c into main Jun 2, 2025
1 check was pending
@jpark0506 jpark0506 deleted the feat/CCI-4 branch June 2, 2025 11:59
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

♻️ Duplicate comments (1)
app/workspace/interview/group/community/[id]/join/page.tsx (1)

3-19: Remove Promise-based params & experimental use() hook as recommended in previous review.

This issue was flagged in a previous review but remains unaddressed. Since this is a client component, params should be accessed synchronously.

Apply the previously suggested fix:

-import { useState, use as usePromise } from "react"
+import { useState } from "react"-export default function JoinGroupInterviewPage({ params }: { params: Promise<{ id: string }> }) {
-  const { id: postId } = usePromise(params)
+export default function JoinGroupInterviewPage({ params }: { params: { id: string } }) {
+  const { id: postId } = params
🧹 Nitpick comments (1)
app/workspace/interview/group/community/[id]/join/page.tsx (1)

154-162: Improve accessibility and user experience for empty states.

The current implementation shows disabled placeholder text for empty lists, but this creates poor accessibility and UX.

                    <SelectContent>
-                      {resumes.length === 0 ? (
-                        <div className="px-3 py-2 text-gray-400 text-sm">이력서가 없습니다</div>
-                      ) : (
+                      {resumes.length === 0 ? (
+                        <SelectItem value="" disabled>
+                          이력서가 없습니다
+                        </SelectItem>
+                      ) : (
                        resumes.map((resume) => (
                          <SelectItem key={resume.resumeId} value={String(resume.resumeId)}>
                            {resume.fileName}
                          </SelectItem>
                        ))
-                      )}
+                      )}

Apply the same pattern to cover letters. This ensures proper Select component behavior and accessibility.

Also applies to: 174-182

📜 Review details

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

📥 Commits

Reviewing files that changed from the base of the PR and between d86a621 and 241c820.

📒 Files selected for processing (2)
  • app/workspace/interview/group/community/[id]/join/page.tsx (7 hunks)
  • components/interview/steps/Step4Group.tsx (1 hunks)
🔇 Additional comments (1)
components/interview/steps/Step4Group.tsx (1)

92-97: LGTM! Logical improvement to form state management.

The change appropriately sets startType to "scheduled" when a date is selected, ensuring consistent form state. This improves the user experience by automatically configuring the interview type based on the user's date selection.

Comment on lines +74 to 86
// 에러/호스트 본인 체크 후 뒤로 이동 처리
if (!interviewLoading && !resumeLoading && !coverletterLoading) {
if (interviewError || resumeError || coverletterError || !post) {
alert('데이터를 불러오지 못했습니다.')
if (typeof window !== 'undefined') window.history.back()
return null
}
if (memberId && post.hostName && String(memberId) === post.hostName) {
alert('본인은 자신의 면접에 참여할 수 없습니다.')
if (typeof window !== 'undefined') window.history.back()
return null
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Improve error handling and navigation.

The current error handling has several issues:

  • Using window.history.back() can be unreliable
  • Multiple conditions in a single block make debugging difficult
  • Browser compatibility concerns with window checks
-  // 에러/호스트 본인 체크 후 뒤로 이동 처리
-  if (!interviewLoading && !resumeLoading && !coverletterLoading) {
-    if (interviewError || resumeError || coverletterError || !post) {
-      alert('데이터를 불러오지 못했습니다.')
-      if (typeof window !== 'undefined') window.history.back()
-      return null
-    }
-    if (memberId && post.hostName && String(memberId) === post.hostName) {
-      alert('본인은 자신의 면접에 참여할 수 없습니다.')
-      if (typeof window !== 'undefined') window.history.back()
-      return null
-    }
-  }
+  const router = useRouter()
+  
+  // Error handling
+  useEffect(() => {
+    if (!interviewLoading && !resumeLoading && !coverletterLoading) {
+      if (interviewError || resumeError || coverletterError || !post) {
+        alert('데이터를 불러오지 못했습니다.')
+        router.back()
+        return
+      }
+      if (memberId && post.hostId && memberId === post.hostId) {
+        alert('본인은 자신의 면접에 참여할 수 없습니다.')
+        router.back()
+        return
+      }
+    }
+  }, [interviewLoading, resumeLoading, coverletterLoading, interviewError, resumeError, coverletterError, post, memberId, router])

Don't forget to import useRouter from next/navigation.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In app/workspace/interview/group/community/[id]/join/page.tsx around lines 74 to
86, replace the use of window.history.back() with Next.js's useRouter hook for
navigation to ensure reliability and compatibility. Refactor the error handling
by separating the conditions into distinct if blocks for clearer debugging and
maintainability. Also, add the import statement for useRouter from
next/navigation at the top of the file.

if (typeof window !== 'undefined') window.history.back()
return null
}
if (memberId && post.hostName && String(memberId) === post.hostName) {
Copy link
Contributor

Choose a reason for hiding this comment

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

💡 Verification agent

🧩 Analysis chain

Fix incorrect host validation logic.

The comparison between memberId (number) and hostName (string) is logically incorrect. If hostName represents the host's name rather than ID, this validation will never work properly.

-    if (memberId && post.hostName && String(memberId) === post.hostName) {
+    if (memberId && post.hostId && memberId === post.hostId) {

Alternatively, if the API doesn't provide hostId, verify the correct field name in the interview data structure to properly identify the host.


🏁 Script executed:

#!/bin/bash
# Verify the structure of GroupInterviewDetailDTO to identify the correct host identifier field
ast-grep --pattern 'interface GroupInterviewDetailDTO {
  $$$
}'

Length of output: 862


Fix host validation logic

The GroupInterviewDetailDTO includes only hostName?: string (no hostId), so this check will always fail—it’s comparing a numeric memberId to a user name:

if (memberId && post.hostName && String(memberId) === post.hostName) {  }

To correct this:

  • Preferred: Extend the API/DTO to provide a hostId: number, then update to:
    - if (memberId && post.hostName && String(memberId) === post.hostName) {
    + if (memberId && post.hostId && memberId === post.hostId) {
        // host-only logic
      }
  • Alternative (no API change): Derive the host’s ID from groupInterviewParticipants. For example, if participants include an isHost flag or role:
    const host = post.groupInterviewParticipants?.find(p => p.isHost);
    if (memberId && host && memberId === host.memberId) {
      // host-only logic
    }

Ensure the front end and API agree on which field identifies the host.

🤖 Prompt for AI Agents
In app/workspace/interview/group/community/[id]/join/page.tsx at line 81, the
current host validation incorrectly compares memberId (a number) to hostName (a
string), which will always fail. To fix this, update the logic to identify the
host by their memberId instead of hostName. If the API does not provide a hostId
directly, find the host from post.groupInterviewParticipants by checking for an
isHost flag or equivalent, then compare memberId to that participant's memberId
for validation. Adjust the code to use this correct host identification method
to ensure proper host validation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant