<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Vpatel29</id>
	<title>Expertiza_Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.expertiza.ncsu.edu/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Vpatel29"/>
	<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=Special:Contributions/Vpatel29"/>
	<updated>2026-06-29T00:20:42Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.41.0</generator>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025_-_E2565._Integration_of_JoinTeamRequests&amp;diff=167109</id>
		<title>CSC/ECE 517 Fall 2025 - E2565. Integration of JoinTeamRequests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025_-_E2565._Integration_of_JoinTeamRequests&amp;diff=167109"/>
		<updated>2025-11-11T02:43:34Z</updated>

		<summary type="html">&lt;p&gt;Vpatel29: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= E2565. Integration of JoinTeamRequests =&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document describes the design and implementation plan for integrating JoinTeamRequests functionality in Expertiza. The feature enables students to respond to teammate advertisements by creating join team requests, which topic holders can then approve or decline. This integration will complete the teammate advertisement workflow by connecting the advertisement creation (already implemented) with the join team request flow.&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
Currently, Expertiza supports teammate advertisements for assignments with topics. Topic holders can create advertisements on the &amp;quot;Your Team&amp;quot; page. However, the complete flow for responding to advertisements and managing join team requests is not fully integrated. The following gaps exist:&lt;br /&gt;
&lt;br /&gt;
1. The join_team_requests_controller has action privilege checks scattered across methods instead of using a centralized `action_allowed?` method&lt;br /&gt;
&lt;br /&gt;
2. There is no frontend UI for viewing advertisements on the Signup Sheet page&lt;br /&gt;
&lt;br /&gt;
3. There is no UI for creating join team requests when responding to advertisements&lt;br /&gt;
&lt;br /&gt;
4. The &amp;quot;Received Requests&amp;quot; section is missing from the StudentTeamView page&lt;br /&gt;
&lt;br /&gt;
5. There is no method to accept join team requests (only decline exists)&lt;br /&gt;
&lt;br /&gt;
6. The controller needs better integration with the frontend&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
&lt;br /&gt;
1. Refactor the join_team_requests_controller to use a single `action_allowed?` method for privilege checking&lt;br /&gt;
&lt;br /&gt;
2. Add a trumpet icon on the Signup Sheet page to indicate when advertisements exist for topics&lt;br /&gt;
&lt;br /&gt;
3. Create a frontend UI for viewing advertisements and creating join team requests&lt;br /&gt;
&lt;br /&gt;
4. Add a &amp;quot;Received Requests&amp;quot; section to StudentTeamView.tsx for managing incoming join team requests&lt;br /&gt;
&lt;br /&gt;
5. Implement an accept method for join team requests&lt;br /&gt;
&lt;br /&gt;
6. Ensure proper validation that teams cannot accept requests when full&lt;br /&gt;
&lt;br /&gt;
7. Conduct comprehensive testing of the entire flow&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
=== Backend Design ===&lt;br /&gt;
&lt;br /&gt;
==== Controller Refactoring ====&lt;br /&gt;
&lt;br /&gt;
The `Api::V1::JoinTeamRequestsController` currently has privilege checks scattered across methods:&lt;br /&gt;
&lt;br /&gt;
- `index` method checks for administrator role directly&lt;br /&gt;
- `action_allowed?` only checks if user is a student&lt;br /&gt;
&lt;br /&gt;
'''Refactored Design:'''&lt;br /&gt;
&lt;br /&gt;
The `action_allowed?` method will be enhanced to handle different actions based on the action being performed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
def action_allowed?&lt;br /&gt;
  case action_name.to_sym&lt;br /&gt;
  when :index&lt;br /&gt;
    @current_user.administrator?&lt;br /&gt;
  when :create, :show, :update, :destroy, :decline, :accept&lt;br /&gt;
    @current_user.student?&lt;br /&gt;
  else&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All methods will rely on this centralized privilege check, removing individual checks from methods like `index`.&lt;br /&gt;
&lt;br /&gt;
==== New Methods ====&lt;br /&gt;
&lt;br /&gt;
'''1. Accept Method'''&lt;br /&gt;
&lt;br /&gt;
Add a new `accept` method to handle accepting join team requests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
# PATCH/PUT api/v1/join_team_requests/:id/accept&lt;br /&gt;
# Accepts a join team request and adds the participant to the team&lt;br /&gt;
def accept&lt;br /&gt;
  team = @join_team_request.team&lt;br /&gt;
  &lt;br /&gt;
  # Check if team is full&lt;br /&gt;
  if team.full?&lt;br /&gt;
    return render json: { error: 'This team is full.' }, status: :unprocessable_entity&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Check if participant is already on the team&lt;br /&gt;
  if team.participants.include?(@join_team_request.participant)&lt;br /&gt;
    return render json: { error: 'Participant already belongs to the team' }, status: :unprocessable_entity&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  ActiveRecord::Base.transaction do&lt;br /&gt;
    # Add participant to team&lt;br /&gt;
    result = team.add_member(@join_team_request.participant)&lt;br /&gt;
    &lt;br /&gt;
    if result[:success]&lt;br /&gt;
      # Update request status&lt;br /&gt;
      @join_team_request.update!(reply_status: ACCEPTED)&lt;br /&gt;
      render json: { message: 'JoinTeamRequest accepted successfully', join_team_request: @join_team_request }, status: :ok&lt;br /&gt;
    else&lt;br /&gt;
      render json: { error: result[:error] }, status: :unprocessable_entity&lt;br /&gt;
      raise ActiveRecord::Rollback&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
rescue =&amp;gt; e&lt;br /&gt;
  render json: { error: &amp;quot;Failed to accept request: #{e.message}&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''2. Get Join Team Requests for Team'''&lt;br /&gt;
&lt;br /&gt;
Add a method to fetch all join team requests for a specific team (for the &amp;quot;Received Requests&amp;quot; section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
# GET api/v1/join_team_requests/team/:team_id&lt;br /&gt;
# Gets all join team requests for a specific team&lt;br /&gt;
def team_requests&lt;br /&gt;
  team = Team.find(params[:team_id])&lt;br /&gt;
  &lt;br /&gt;
  # Verify current user is a member of the team&lt;br /&gt;
  unless team.participants.exists?(user_id: @current_user.id)&lt;br /&gt;
    return render json: { error: 'Unauthorized' }, status: :unauthorized&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  join_team_requests = JoinTeamRequest.where(team_id: params[:team_id])&lt;br /&gt;
    .includes(:participant =&amp;gt; :user)&lt;br /&gt;
    .order(created_at: :desc)&lt;br /&gt;
  &lt;br /&gt;
  render json: join_team_requests, status: :ok&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''3. Get Advertisements for Assignment'''&lt;br /&gt;
&lt;br /&gt;
Add a method to fetch all advertisements for an assignment (for the Signup Sheet page):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
# GET api/v1/signed_up_teams/advertisements/:assignment_id&lt;br /&gt;
# Gets all advertisements for an assignment&lt;br /&gt;
def advertisements&lt;br /&gt;
  assignment = Assignment.find(params[:assignment_id])&lt;br /&gt;
  signed_up_teams = SignedUpTeam.joins(:team, :sign_up_topic)&lt;br /&gt;
    .where(sign_up_topics: { assignment_id: params[:assignment_id] })&lt;br /&gt;
    .where(advertise_for_partner: true)&lt;br /&gt;
    .includes(:team, :sign_up_topic)&lt;br /&gt;
  &lt;br /&gt;
  advertisements = signed_up_teams.map do |sut|&lt;br /&gt;
    {&lt;br /&gt;
      id: sut.id,&lt;br /&gt;
      team_id: sut.team_id,&lt;br /&gt;
      team_name: sut.team.name,&lt;br /&gt;
      topic_id: sut.sign_up_topic_id,&lt;br /&gt;
      topic_name: sut.sign_up_topic.topic_name,&lt;br /&gt;
      comments_for_advertisement: sut.comments_for_advertisement,&lt;br /&gt;
      created_at: sut.created_at&lt;br /&gt;
    }&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  render json: advertisements, status: :ok&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Model Updates ====&lt;br /&gt;
&lt;br /&gt;
The `JoinTeamRequest` model needs to establish proper associations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
class JoinTeamRequest &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :team&lt;br /&gt;
  belongs_to :participant&lt;br /&gt;
  &lt;br /&gt;
  ACCEPTED_STATUSES = %w[ACCEPTED DECLINED PENDING]&lt;br /&gt;
  validates :reply_status, inclusion: { in: ACCEPTED_STATUSES }&lt;br /&gt;
  &lt;br /&gt;
  scope :pending, -&amp;gt; { where(reply_status: 'PENDING') }&lt;br /&gt;
  scope :for_team, -&amp;gt;(team_id) { where(team_id: team_id) }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Routes Updates ====&lt;br /&gt;
&lt;br /&gt;
Add new routes for the additional endpoints:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
resources :join_team_requests do&lt;br /&gt;
  collection do&lt;br /&gt;
    get 'team/:team_id', to: 'join_team_requests#team_requests'&lt;br /&gt;
    post 'decline/:id', to: 'join_team_requests#decline'&lt;br /&gt;
    post 'accept/:id', to: 'join_team_requests#accept'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
resources :signed_up_teams do&lt;br /&gt;
collection do&lt;br /&gt;
get 'advertisements/:assignment_id', to: 'signed_up_teams#advertisements'&lt;br /&gt;
end&lt;br /&gt;
member do&lt;br /&gt;
post :create_advertisement&lt;br /&gt;
patch :update_advertisement&lt;br /&gt;
delete :remove_advertisement&lt;br /&gt;
end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Frontend Design ===&lt;br /&gt;
&lt;br /&gt;
==== Signup Sheet Page Enhancement ====&lt;br /&gt;
&lt;br /&gt;
Create a new component or enhance existing signup sheet to display advertisements:&lt;br /&gt;
&lt;br /&gt;
'''Component: SignupSheet.tsx'''&lt;br /&gt;
&lt;br /&gt;
This component will:&lt;br /&gt;
&lt;br /&gt;
- Display all topics for an assignment&lt;br /&gt;
- Show a trumpet icon (🔔) next to topics that have advertisements&lt;br /&gt;
- Allow users to click on topics with advertisements to view details&lt;br /&gt;
- Provide a modal/dialog to view advertisement details and create a join team request&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
interface Advertisement {&lt;br /&gt;
  id: number;&lt;br /&gt;
  team_id: number;&lt;br /&gt;
  team_name: string;&lt;br /&gt;
  topic_id: number;&lt;br /&gt;
  topic_name: string;&lt;br /&gt;
  comments_for_advertisement: string;&lt;br /&gt;
  created_at: string;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
interface SignUpTopic {&lt;br /&gt;
id: number;&lt;br /&gt;
topic_name: string;&lt;br /&gt;
topic_identifier: string;&lt;br /&gt;
max_choosers: number;&lt;br /&gt;
description?: string;&lt;br /&gt;
has_advertisement?: boolean;&lt;br /&gt;
advertisement?: Advertisement;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The UI will show:&lt;br /&gt;
&lt;br /&gt;
- A table/list of topics&lt;br /&gt;
- Trumpet icon indicator for topics with advertisements&lt;br /&gt;
- Click handler to open advertisement details modal&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align:center&amp;quot;&amp;gt;[[File:trumpetSign.png|800px|Figure 1: Signup Sheet page showing trumpet icon indicators for topics with advertisements]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Join Team Request Modal ====&lt;br /&gt;
&lt;br /&gt;
Create a modal component for creating join team requests:&lt;br /&gt;
&lt;br /&gt;
'''Component: JoinTeamRequestModal.tsx'''&lt;br /&gt;
&lt;br /&gt;
This modal will:&lt;br /&gt;
&lt;br /&gt;
- Display advertisement details (team name, topic, desired qualifications)&lt;br /&gt;
- Provide a text area for comments (optional)&lt;br /&gt;
- Show a &amp;quot;Send Request&amp;quot; button&lt;br /&gt;
- Handle form submission and API calls&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align:center&amp;quot;&amp;gt;[[File:viewAdv.png|800px|Figure 2: Modal displaying advertisement details with option to create join team request]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
interface JoinTeamRequestModalProps {&lt;br /&gt;
  show: boolean;&lt;br /&gt;
  onHide: () =&amp;gt; void;&lt;br /&gt;
  advertisement: Advertisement;&lt;br /&gt;
  assignmentId: number;&lt;br /&gt;
  onSuccess: () =&amp;gt; void;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align:center&amp;quot;&amp;gt;[[File:joinReq.png|800px|Figure 3: Join team request creation form with advertisement details and comments field]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== StudentTeamView Enhancement ====&lt;br /&gt;
&lt;br /&gt;
Add a &amp;quot;Received Requests&amp;quot; section to `StudentTeamView.tsx`:&lt;br /&gt;
&lt;br /&gt;
'''Section: Received Join Team Requests'''&lt;br /&gt;
&lt;br /&gt;
This section will:&lt;br /&gt;
&lt;br /&gt;
- Display all pending join team requests for the current team&lt;br /&gt;
- Show request details: requester name, email, comments, date&lt;br /&gt;
- Provide &amp;quot;Approve&amp;quot; and &amp;quot;Decline&amp;quot; buttons for each request&lt;br /&gt;
- Disable approve button if team is full&lt;br /&gt;
- Show status for non-pending requests&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
interface JoinTeamRequest {&lt;br /&gt;
  id: number;&lt;br /&gt;
  participant_id: number;&lt;br /&gt;
  team_id: number;&lt;br /&gt;
  comments: string;&lt;br /&gt;
  reply_status: 'PENDING' | 'ACCEPTED' | 'DECLINED';&lt;br /&gt;
  created_at: string;&lt;br /&gt;
  participant: {&lt;br /&gt;
    id: number;&lt;br /&gt;
    user: {&lt;br /&gt;
      id: number;&lt;br /&gt;
      name: string;&lt;br /&gt;
      full_name: string;&lt;br /&gt;
      email: string;&lt;br /&gt;
    };&lt;br /&gt;
  };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The UI structure will be similar to the existing &amp;quot;Received Invitations&amp;quot; section, with:&lt;br /&gt;
&lt;br /&gt;
- Table displaying request information&lt;br /&gt;
- Action buttons (Approve/Decline) for pending requests&lt;br /&gt;
- Status display for processed requests&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align:center&amp;quot;&amp;gt;[[File:allReq.png|800px|Figure 4: Received Requests section in StudentTeamView showing all join team requests with approve/decline options]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== API Hooks ====&lt;br /&gt;
&lt;br /&gt;
Create or extend hooks for join team requests:&lt;br /&gt;
&lt;br /&gt;
'''File: hooks/useJoinTeamRequest.ts'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
export const useJoinTeamRequest = () =&amp;gt; {&lt;br /&gt;
  const createRequestAPI = useAPI();&lt;br /&gt;
  const acceptRequestAPI = useAPI();&lt;br /&gt;
  const declineRequestAPI = useAPI();&lt;br /&gt;
  const fetchTeamRequestsAPI = useAPI();&lt;br /&gt;
  const fetchAdvertisementsAPI = useAPI();&lt;br /&gt;
&lt;br /&gt;
const createJoinTeamRequest = (teamId: number, assignmentId: number, comments?: string) =&amp;gt;&lt;br /&gt;
createRequestAPI.sendRequest({&lt;br /&gt;
url: `/join_team_requests`,&lt;br /&gt;
method: 'POST',&lt;br /&gt;
data: { team_id: teamId, assignment_id: assignmentId, comments }&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
const acceptJoinTeamRequest = (requestId: number) =&amp;gt;&lt;br /&gt;
acceptRequestAPI.sendRequest({&lt;br /&gt;
url: `/join_team_requests/accept/${requestId}`,&lt;br /&gt;
method: 'POST'&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
const declineJoinTeamRequest = (requestId: number) =&amp;gt;&lt;br /&gt;
declineRequestAPI.sendRequest({&lt;br /&gt;
url: `/join_team_requests/decline/${requestId}`,&lt;br /&gt;
method: 'POST'&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
const fetchTeamRequests = (teamId: number) =&amp;gt;&lt;br /&gt;
fetchTeamRequestsAPI.sendRequest({&lt;br /&gt;
url: `/join_team_requests/team/${teamId}`&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
const fetchAdvertisements = (assignmentId: number) =&amp;gt;&lt;br /&gt;
fetchAdvertisementsAPI.sendRequest({&lt;br /&gt;
url: `/signed_up_teams/advertisements/${assignmentId}`&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
createJoinTeamRequest,&lt;br /&gt;
acceptJoinTeamRequest,&lt;br /&gt;
declineJoinTeamRequest,&lt;br /&gt;
fetchTeamRequests,&lt;br /&gt;
fetchAdvertisements,&lt;br /&gt;
createRequestAPI,&lt;br /&gt;
acceptRequestAPI,&lt;br /&gt;
declineRequestAPI,&lt;br /&gt;
fetchTeamRequestsAPI,&lt;br /&gt;
fetchAdvertisementsAPI&lt;br /&gt;
};&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementation Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Phase 1: Backend Refactoring ===&lt;br /&gt;
&lt;br /&gt;
1. '''Refactor action_allowed? method'''&lt;br /&gt;
   a. Update `Api::V1::JoinTeamRequestsController#action_allowed?` to handle all actions&lt;br /&gt;
   b. Remove individual privilege checks from `index` method&lt;br /&gt;
   c. Ensure all actions go through the centralized check&lt;br /&gt;
2. '''Add accept method'''&lt;br /&gt;
   a. Implement `accept` method with team full validation&lt;br /&gt;
   b. Add transaction handling for atomic operations&lt;br /&gt;
   c. Update request status to ACCEPTED&lt;br /&gt;
   d. Add participant to team using `team.add_member`&lt;br /&gt;
3. '''Add team_requests method'''&lt;br /&gt;
   a. Implement method to fetch requests for a team&lt;br /&gt;
   b. Add authorization check (user must be team member)&lt;br /&gt;
   c. Include participant and user data in response&lt;br /&gt;
4. '''Add advertisements method to SignedUpTeamsController'''&lt;br /&gt;
   a. Implement method to fetch all advertisements for an assignment&lt;br /&gt;
   b. Join with teams and sign_up_topics&lt;br /&gt;
   c. Return formatted advertisement data&lt;br /&gt;
5. '''Update JoinTeamRequest model'''&lt;br /&gt;
   a. Add `belongs_to :team` association&lt;br /&gt;
   b. Add scopes for filtering&lt;br /&gt;
   c. Update validations&lt;br /&gt;
6. '''Update routes'''&lt;br /&gt;
   a. Add routes for new endpoints&lt;br /&gt;
   b. Ensure RESTful conventions&lt;br /&gt;
&lt;br /&gt;
=== Phase 2: Frontend - Signup Sheet ===&lt;br /&gt;
&lt;br /&gt;
1. '''Create SignupSheet component (if not exists)'''&lt;br /&gt;
   a. Display topics for an assignment&lt;br /&gt;
   b. Fetch advertisements for the assignment&lt;br /&gt;
   c. Map advertisements to topics&lt;br /&gt;
   d. Display trumpet icon for topics with advertisements&lt;br /&gt;
2. '''Create JoinTeamRequestModal component'''&lt;br /&gt;
   a. Design modal UI&lt;br /&gt;
   b. Implement form with comments field&lt;br /&gt;
   c. Add submit handler&lt;br /&gt;
   d. Handle success/error states&lt;br /&gt;
3. '''Integrate modal with SignupSheet'''&lt;br /&gt;
   a. Add click handler for topics with advertisements&lt;br /&gt;
   b. Open modal with advertisement details&lt;br /&gt;
   c. Handle modal close&lt;br /&gt;
&lt;br /&gt;
=== Phase 3: Frontend - StudentTeamView ===&lt;br /&gt;
&lt;br /&gt;
1. '''Add Received Requests section'''&lt;br /&gt;
   a. Create section similar to &amp;quot;Received Invitations&amp;quot;&lt;br /&gt;
   b. Fetch join team requests for current team&lt;br /&gt;
   c. Display requests in table format&lt;br /&gt;
2. '''Implement approve/decline functionality'''&lt;br /&gt;
   a. Add approve button handler&lt;br /&gt;
   b. Add decline button handler&lt;br /&gt;
   c. Check team full status before allowing approve&lt;br /&gt;
   d. Update UI after actions&lt;br /&gt;
3. '''Add useJoinTeamRequest hook'''&lt;br /&gt;
   a. Create hook file&lt;br /&gt;
   b. Implement all API methods&lt;br /&gt;
   c. Export hook for use in components&lt;br /&gt;
&lt;br /&gt;
=== Phase 4: Integration and Testing ===&lt;br /&gt;
&lt;br /&gt;
1. '''End-to-end testing'''&lt;br /&gt;
   a. Test advertisement creation → request creation → approval flow&lt;br /&gt;
   b. Test decline flow&lt;br /&gt;
   c. Test team full validation&lt;br /&gt;
   d. Test authorization checks&lt;br /&gt;
2. '''Unit testing'''&lt;br /&gt;
   a. Test controller methods&lt;br /&gt;
   b. Test model validations&lt;br /&gt;
   c. Test frontend components&lt;br /&gt;
3. '''Integration testing'''&lt;br /&gt;
   a. Test API endpoints&lt;br /&gt;
   b. Test frontend-backend integration&lt;br /&gt;
   c. Test error handling&lt;br /&gt;
&lt;br /&gt;
== Files Changed/Added ==&lt;br /&gt;
&lt;br /&gt;
=== Backend Files ===&lt;br /&gt;
&lt;br /&gt;
'''Modified:'''&lt;br /&gt;
&lt;br /&gt;
- `app/controllers/api/v1/join_team_requests_controller.rb` - Refactor action_allowed?, add accept and team_requests methods&lt;br /&gt;
- `app/controllers/api/v1/signed_up_teams_controller.rb` - Add advertisements method&lt;br /&gt;
- `app/models/join_team_request.rb` - Add associations and scopes&lt;br /&gt;
- `config/routes.rb` - Add new routes&lt;br /&gt;
&lt;br /&gt;
'''Added:'''&lt;br /&gt;
&lt;br /&gt;
- `spec/requests/api/v1/join_team_requests_spec.rb` - Request specs for new methods&lt;br /&gt;
- `spec/models/join_team_request_spec.rb` - Model specs&lt;br /&gt;
&lt;br /&gt;
=== Frontend Files ===&lt;br /&gt;
&lt;br /&gt;
'''Modified:'''&lt;br /&gt;
&lt;br /&gt;
- `src/pages/Student Teams/StudentTeamView.tsx` - Add Received Requests section&lt;br /&gt;
- `src/hooks/useStudentTeam.ts` - Add join team request methods (or create new hook)&lt;br /&gt;
&lt;br /&gt;
'''Added:'''&lt;br /&gt;
&lt;br /&gt;
- `src/pages/SignUpSheet/SignUpSheet.tsx` - Signup sheet component with advertisement indicators&lt;br /&gt;
- `src/pages/SignUpSheet/JoinTeamRequestModal.tsx` - Modal for creating join team requests&lt;br /&gt;
- `src/hooks/useJoinTeamRequest.ts` - Hook for join team request API calls&lt;br /&gt;
- `src/pages/SignUpSheet/SignUpSheet.module.css` - Styles for signup sheet&lt;br /&gt;
- `src/pages/SignUpSheet/JoinTeamRequestModal.module.css` - Styles for modal&lt;br /&gt;
&lt;br /&gt;
== Testing Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Backend Testing ===&lt;br /&gt;
&lt;br /&gt;
==== Unit Tests ====&lt;br /&gt;
&lt;br /&gt;
1. '''JoinTeamRequestsController Tests'''&lt;br /&gt;
   a. Test action_allowed? for different actions and user roles&lt;br /&gt;
   b. Test accept method with valid request&lt;br /&gt;
   c. Test accept method when team is full&lt;br /&gt;
   d. Test accept method when participant already on team&lt;br /&gt;
   e. Test team_requests method authorization&lt;br /&gt;
   f. Test team_requests method returns correct data&lt;br /&gt;
2. '''SignedUpTeamsController Tests'''&lt;br /&gt;
   a. Test advertisements method returns correct data&lt;br /&gt;
   b. Test advertisements method filters correctly&lt;br /&gt;
3. '''JoinTeamRequest Model Tests'''&lt;br /&gt;
   a. Test associations&lt;br /&gt;
   b. Test validations&lt;br /&gt;
   c. Test scopes&lt;br /&gt;
&lt;br /&gt;
==== Integration Tests ====&lt;br /&gt;
&lt;br /&gt;
1. '''End-to-End Flow Tests'''&lt;br /&gt;
   a. Create advertisement → Create join request → Accept request&lt;br /&gt;
   b. Create advertisement → Create join request → Decline request&lt;br /&gt;
   c. Test team full validation prevents acceptance&lt;br /&gt;
   d. Test authorization prevents unauthorized access&lt;br /&gt;
&lt;br /&gt;
=== Frontend Testing ===&lt;br /&gt;
&lt;br /&gt;
==== Component Tests ====&lt;br /&gt;
&lt;br /&gt;
1. '''SignUpSheet Component'''&lt;br /&gt;
   a. Test advertisement indicators display correctly&lt;br /&gt;
   b. Test modal opens on click&lt;br /&gt;
   c. Test data fetching&lt;br /&gt;
2. '''JoinTeamRequestModal Component'''&lt;br /&gt;
   a. Test form submission&lt;br /&gt;
   b. Test validation&lt;br /&gt;
   c. Test success/error handling&lt;br /&gt;
3. '''StudentTeamView Component'''&lt;br /&gt;
   a. Test Received Requests section displays&lt;br /&gt;
   b. Test approve functionality&lt;br /&gt;
   c. Test decline functionality&lt;br /&gt;
   d. Test team full validation&lt;br /&gt;
&lt;br /&gt;
==== Integration Tests ====&lt;br /&gt;
&lt;br /&gt;
1. '''API Integration'''&lt;br /&gt;
   a. Test all API calls work correctly&lt;br /&gt;
   b. Test error handling&lt;br /&gt;
   c. Test loading states&lt;br /&gt;
&lt;br /&gt;
== Edge Cases and Error Handling ==&lt;br /&gt;
&lt;br /&gt;
=== Backend Edge Cases ===&lt;br /&gt;
&lt;br /&gt;
1. '''Team Full Validation'''&lt;br /&gt;
   - Check team capacity before accepting request&lt;br /&gt;
   - Return appropriate error message&lt;br /&gt;
   - Prevent race conditions with database transactions&lt;br /&gt;
2. '''Authorization'''&lt;br /&gt;
   - Verify user is team member before showing requests&lt;br /&gt;
   - Verify user is student before creating requests&lt;br /&gt;
   - Verify user is administrator before viewing all requests&lt;br /&gt;
3. '''Duplicate Requests'''&lt;br /&gt;
   - Prevent creating duplicate requests from same participant&lt;br /&gt;
   - Handle case where participant already on team&lt;br /&gt;
4. '''Concurrent Modifications'''&lt;br /&gt;
   - Use transactions for atomic operations&lt;br /&gt;
   - Handle race conditions in team membership updates&lt;br /&gt;
&lt;br /&gt;
=== Frontend Edge Cases ===&lt;br /&gt;
&lt;br /&gt;
1. '''Network Errors'''&lt;br /&gt;
   - Display appropriate error messages&lt;br /&gt;
   - Handle timeout scenarios&lt;br /&gt;
   - Provide retry mechanisms&lt;br /&gt;
2. '''Empty States'''&lt;br /&gt;
   - Show appropriate messages when no advertisements exist&lt;br /&gt;
   - Show appropriate messages when no requests exist&lt;br /&gt;
3. '''Loading States'''&lt;br /&gt;
   - Display loading indicators during API calls&lt;br /&gt;
   - Prevent multiple simultaneous requests&lt;br /&gt;
4. '''Form Validation'''&lt;br /&gt;
   - Validate required fields&lt;br /&gt;
   - Provide user feedback for errors&lt;br /&gt;
&lt;br /&gt;
== Security Considerations ==&lt;br /&gt;
&lt;br /&gt;
1. '''Authorization Checks'''&lt;br /&gt;
   - All endpoints must verify user permissions&lt;br /&gt;
   - Team members can only see requests for their team&lt;br /&gt;
   - Students can only create requests for themselves&lt;br /&gt;
2. '''Input Validation'''&lt;br /&gt;
   - Sanitize all user inputs&lt;br /&gt;
   - Validate team_id and assignment_id parameters&lt;br /&gt;
   - Prevent SQL injection through parameterized queries&lt;br /&gt;
3. '''Rate Limiting'''&lt;br /&gt;
   - Consider rate limiting for request creation&lt;br /&gt;
   - Prevent spam requests&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
- Expertiza Wiki: E2252. Refactor auth controller.rb &amp;amp; password retrieval controller.rb&lt;br /&gt;
- Rails API Documentation&lt;br /&gt;
- React Router Documentation&lt;br /&gt;
- Expertiza Codebase: Existing invitation and team management implementations&lt;/div&gt;</summary>
		<author><name>Vpatel29</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025_-_E2565._Integration_of_JoinTeamRequests&amp;diff=167108</id>
		<title>CSC/ECE 517 Fall 2025 - E2565. Integration of JoinTeamRequests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025_-_E2565._Integration_of_JoinTeamRequests&amp;diff=167108"/>
		<updated>2025-11-11T02:34:01Z</updated>

		<summary type="html">&lt;p&gt;Vpatel29: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= E2565. Integration of JoinTeamRequests =&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document describes the design and implementation plan for integrating JoinTeamRequests functionality in Expertiza. The feature enables students to respond to teammate advertisements by creating join team requests, which topic holders can then approve or decline. This integration will complete the teammate advertisement workflow by connecting the advertisement creation (already implemented) with the join team request flow.&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
Currently, Expertiza supports teammate advertisements for assignments with topics. Topic holders can create advertisements on the &amp;quot;Your Team&amp;quot; page. However, the complete flow for responding to advertisements and managing join team requests is not fully integrated. The following gaps exist:&lt;br /&gt;
&lt;br /&gt;
# The join_team_requests_controller has action privilege checks scattered across methods instead of using a centralized `action_allowed?` method&lt;br /&gt;
# There is no frontend UI for viewing advertisements on the Signup Sheet page&lt;br /&gt;
# There is no UI for creating join team requests when responding to advertisements&lt;br /&gt;
# The &amp;quot;Received Requests&amp;quot; section is missing from the StudentTeamView page&lt;br /&gt;
# There is no method to accept join team requests (only decline exists)&lt;br /&gt;
# The controller needs better integration with the frontend&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
&lt;br /&gt;
# Refactor the join_team_requests_controller to use a single `action_allowed?` method for privilege checking&lt;br /&gt;
# Add a trumpet icon on the Signup Sheet page to indicate when advertisements exist for topics&lt;br /&gt;
# Create a frontend UI for viewing advertisements and creating join team requests&lt;br /&gt;
# Add a &amp;quot;Received Requests&amp;quot; section to StudentTeamView.tsx for managing incoming join team requests&lt;br /&gt;
# Implement an accept method for join team requests&lt;br /&gt;
# Ensure proper validation that teams cannot accept requests when full&lt;br /&gt;
# Conduct comprehensive testing of the entire flow&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
=== Backend Design ===&lt;br /&gt;
&lt;br /&gt;
==== Controller Refactoring ====&lt;br /&gt;
&lt;br /&gt;
The `Api::V1::JoinTeamRequestsController` currently has privilege checks scattered across methods:&lt;br /&gt;
&lt;br /&gt;
- `index` method checks for administrator role directly&lt;br /&gt;
- `action_allowed?` only checks if user is a student&lt;br /&gt;
&lt;br /&gt;
'''Refactored Design:'''&lt;br /&gt;
&lt;br /&gt;
The `action_allowed?` method will be enhanced to handle different actions based on the action being performed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
def action_allowed?&lt;br /&gt;
  case action_name.to_sym&lt;br /&gt;
  when :index&lt;br /&gt;
    @current_user.administrator?&lt;br /&gt;
  when :create, :show, :update, :destroy, :decline, :accept&lt;br /&gt;
    @current_user.student?&lt;br /&gt;
  else&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All methods will rely on this centralized privilege check, removing individual checks from methods like `index`.&lt;br /&gt;
&lt;br /&gt;
==== New Methods ====&lt;br /&gt;
&lt;br /&gt;
'''1. Accept Method'''&lt;br /&gt;
&lt;br /&gt;
Add a new `accept` method to handle accepting join team requests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
# PATCH/PUT api/v1/join_team_requests/:id/accept&lt;br /&gt;
# Accepts a join team request and adds the participant to the team&lt;br /&gt;
def accept&lt;br /&gt;
  team = @join_team_request.team&lt;br /&gt;
  &lt;br /&gt;
  # Check if team is full&lt;br /&gt;
  if team.full?&lt;br /&gt;
    return render json: { error: 'This team is full.' }, status: :unprocessable_entity&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Check if participant is already on the team&lt;br /&gt;
  if team.participants.include?(@join_team_request.participant)&lt;br /&gt;
    return render json: { error: 'Participant already belongs to the team' }, status: :unprocessable_entity&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  ActiveRecord::Base.transaction do&lt;br /&gt;
    # Add participant to team&lt;br /&gt;
    result = team.add_member(@join_team_request.participant)&lt;br /&gt;
    &lt;br /&gt;
    if result[:success]&lt;br /&gt;
      # Update request status&lt;br /&gt;
      @join_team_request.update!(reply_status: ACCEPTED)&lt;br /&gt;
      render json: { message: 'JoinTeamRequest accepted successfully', join_team_request: @join_team_request }, status: :ok&lt;br /&gt;
    else&lt;br /&gt;
      render json: { error: result[:error] }, status: :unprocessable_entity&lt;br /&gt;
      raise ActiveRecord::Rollback&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
rescue =&amp;gt; e&lt;br /&gt;
  render json: { error: &amp;quot;Failed to accept request: #{e.message}&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''2. Get Join Team Requests for Team'''&lt;br /&gt;
&lt;br /&gt;
Add a method to fetch all join team requests for a specific team (for the &amp;quot;Received Requests&amp;quot; section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
# GET api/v1/join_team_requests/team/:team_id&lt;br /&gt;
# Gets all join team requests for a specific team&lt;br /&gt;
def team_requests&lt;br /&gt;
  team = Team.find(params[:team_id])&lt;br /&gt;
  &lt;br /&gt;
  # Verify current user is a member of the team&lt;br /&gt;
  unless team.participants.exists?(user_id: @current_user.id)&lt;br /&gt;
    return render json: { error: 'Unauthorized' }, status: :unauthorized&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  join_team_requests = JoinTeamRequest.where(team_id: params[:team_id])&lt;br /&gt;
    .includes(:participant =&amp;gt; :user)&lt;br /&gt;
    .order(created_at: :desc)&lt;br /&gt;
  &lt;br /&gt;
  render json: join_team_requests, status: :ok&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''3. Get Advertisements for Assignment'''&lt;br /&gt;
&lt;br /&gt;
Add a method to fetch all advertisements for an assignment (for the Signup Sheet page):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
# GET api/v1/signed_up_teams/advertisements/:assignment_id&lt;br /&gt;
# Gets all advertisements for an assignment&lt;br /&gt;
def advertisements&lt;br /&gt;
  assignment = Assignment.find(params[:assignment_id])&lt;br /&gt;
  signed_up_teams = SignedUpTeam.joins(:team, :sign_up_topic)&lt;br /&gt;
    .where(sign_up_topics: { assignment_id: params[:assignment_id] })&lt;br /&gt;
    .where(advertise_for_partner: true)&lt;br /&gt;
    .includes(:team, :sign_up_topic)&lt;br /&gt;
  &lt;br /&gt;
  advertisements = signed_up_teams.map do |sut|&lt;br /&gt;
    {&lt;br /&gt;
      id: sut.id,&lt;br /&gt;
      team_id: sut.team_id,&lt;br /&gt;
      team_name: sut.team.name,&lt;br /&gt;
      topic_id: sut.sign_up_topic_id,&lt;br /&gt;
      topic_name: sut.sign_up_topic.topic_name,&lt;br /&gt;
      comments_for_advertisement: sut.comments_for_advertisement,&lt;br /&gt;
      created_at: sut.created_at&lt;br /&gt;
    }&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  render json: advertisements, status: :ok&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Model Updates ====&lt;br /&gt;
&lt;br /&gt;
The `JoinTeamRequest` model needs to establish proper associations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
class JoinTeamRequest &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :team&lt;br /&gt;
  belongs_to :participant&lt;br /&gt;
  &lt;br /&gt;
  ACCEPTED_STATUSES = %w[ACCEPTED DECLINED PENDING]&lt;br /&gt;
  validates :reply_status, inclusion: { in: ACCEPTED_STATUSES }&lt;br /&gt;
  &lt;br /&gt;
  scope :pending, -&amp;gt; { where(reply_status: 'PENDING') }&lt;br /&gt;
  scope :for_team, -&amp;gt;(team_id) { where(team_id: team_id) }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Routes Updates ====&lt;br /&gt;
&lt;br /&gt;
Add new routes for the additional endpoints:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
resources :join_team_requests do&lt;br /&gt;
  collection do&lt;br /&gt;
    get 'team/:team_id', to: 'join_team_requests#team_requests'&lt;br /&gt;
    post 'decline/:id', to: 'join_team_requests#decline'&lt;br /&gt;
    post 'accept/:id', to: 'join_team_requests#accept'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
resources :signed_up_teams do&lt;br /&gt;
collection do&lt;br /&gt;
get 'advertisements/:assignment_id', to: 'signed_up_teams#advertisements'&lt;br /&gt;
end&lt;br /&gt;
member do&lt;br /&gt;
post :create_advertisement&lt;br /&gt;
patch :update_advertisement&lt;br /&gt;
delete :remove_advertisement&lt;br /&gt;
end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Frontend Design ===&lt;br /&gt;
&lt;br /&gt;
==== Signup Sheet Page Enhancement ====&lt;br /&gt;
&lt;br /&gt;
Create a new component or enhance existing signup sheet to display advertisements:&lt;br /&gt;
&lt;br /&gt;
'''Component: SignupSheet.tsx'''&lt;br /&gt;
&lt;br /&gt;
This component will:&lt;br /&gt;
&lt;br /&gt;
- Display all topics for an assignment&lt;br /&gt;
- Show a trumpet icon (🔔) next to topics that have advertisements&lt;br /&gt;
- Allow users to click on topics with advertisements to view details&lt;br /&gt;
- Provide a modal/dialog to view advertisement details and create a join team request&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
interface Advertisement {&lt;br /&gt;
  id: number;&lt;br /&gt;
  team_id: number;&lt;br /&gt;
  team_name: string;&lt;br /&gt;
  topic_id: number;&lt;br /&gt;
  topic_name: string;&lt;br /&gt;
  comments_for_advertisement: string;&lt;br /&gt;
  created_at: string;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
interface SignUpTopic {&lt;br /&gt;
id: number;&lt;br /&gt;
topic_name: string;&lt;br /&gt;
topic_identifier: string;&lt;br /&gt;
max_choosers: number;&lt;br /&gt;
description?: string;&lt;br /&gt;
has_advertisement?: boolean;&lt;br /&gt;
advertisement?: Advertisement;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The UI will show:&lt;br /&gt;
&lt;br /&gt;
- A table/list of topics&lt;br /&gt;
- Trumpet icon indicator for topics with advertisements&lt;br /&gt;
- Click handler to open advertisement details modal&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align:center&amp;quot;&amp;gt;[[File:trumpetSign.png|800px|Figure 1: Signup Sheet page showing trumpet icon indicators for topics with advertisements]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Join Team Request Modal ====&lt;br /&gt;
&lt;br /&gt;
Create a modal component for creating join team requests:&lt;br /&gt;
&lt;br /&gt;
'''Component: JoinTeamRequestModal.tsx'''&lt;br /&gt;
&lt;br /&gt;
This modal will:&lt;br /&gt;
&lt;br /&gt;
- Display advertisement details (team name, topic, desired qualifications)&lt;br /&gt;
- Provide a text area for comments (optional)&lt;br /&gt;
- Show a &amp;quot;Send Request&amp;quot; button&lt;br /&gt;
- Handle form submission and API calls&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align:center&amp;quot;&amp;gt;[[File:viewAdv.png|800px|Figure 2: Modal displaying advertisement details with option to create join team request]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
interface JoinTeamRequestModalProps {&lt;br /&gt;
  show: boolean;&lt;br /&gt;
  onHide: () =&amp;gt; void;&lt;br /&gt;
  advertisement: Advertisement;&lt;br /&gt;
  assignmentId: number;&lt;br /&gt;
  onSuccess: () =&amp;gt; void;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align:center&amp;quot;&amp;gt;[[File:joinReq.png|800px|Figure 3: Join team request creation form with advertisement details and comments field]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== StudentTeamView Enhancement ====&lt;br /&gt;
&lt;br /&gt;
Add a &amp;quot;Received Requests&amp;quot; section to `StudentTeamView.tsx`:&lt;br /&gt;
&lt;br /&gt;
'''Section: Received Join Team Requests'''&lt;br /&gt;
&lt;br /&gt;
This section will:&lt;br /&gt;
&lt;br /&gt;
- Display all pending join team requests for the current team&lt;br /&gt;
- Show request details: requester name, email, comments, date&lt;br /&gt;
- Provide &amp;quot;Approve&amp;quot; and &amp;quot;Decline&amp;quot; buttons for each request&lt;br /&gt;
- Disable approve button if team is full&lt;br /&gt;
- Show status for non-pending requests&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
interface JoinTeamRequest {&lt;br /&gt;
  id: number;&lt;br /&gt;
  participant_id: number;&lt;br /&gt;
  team_id: number;&lt;br /&gt;
  comments: string;&lt;br /&gt;
  reply_status: 'PENDING' | 'ACCEPTED' | 'DECLINED';&lt;br /&gt;
  created_at: string;&lt;br /&gt;
  participant: {&lt;br /&gt;
    id: number;&lt;br /&gt;
    user: {&lt;br /&gt;
      id: number;&lt;br /&gt;
      name: string;&lt;br /&gt;
      full_name: string;&lt;br /&gt;
      email: string;&lt;br /&gt;
    };&lt;br /&gt;
  };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The UI structure will be similar to the existing &amp;quot;Received Invitations&amp;quot; section, with:&lt;br /&gt;
&lt;br /&gt;
- Table displaying request information&lt;br /&gt;
- Action buttons (Approve/Decline) for pending requests&lt;br /&gt;
- Status display for processed requests&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div style=&amp;quot;text-align:center&amp;quot;&amp;gt;[[File:allReq.png|800px|Figure 4: Received Requests section in StudentTeamView showing all join team requests with approve/decline options]]&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== API Hooks ====&lt;br /&gt;
&lt;br /&gt;
Create or extend hooks for join team requests:&lt;br /&gt;
&lt;br /&gt;
'''File: hooks/useJoinTeamRequest.ts'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
export const useJoinTeamRequest = () =&amp;gt; {&lt;br /&gt;
  const createRequestAPI = useAPI();&lt;br /&gt;
  const acceptRequestAPI = useAPI();&lt;br /&gt;
  const declineRequestAPI = useAPI();&lt;br /&gt;
  const fetchTeamRequestsAPI = useAPI();&lt;br /&gt;
  const fetchAdvertisementsAPI = useAPI();&lt;br /&gt;
&lt;br /&gt;
const createJoinTeamRequest = (teamId: number, assignmentId: number, comments?: string) =&amp;gt;&lt;br /&gt;
createRequestAPI.sendRequest({&lt;br /&gt;
url: `/join_team_requests`,&lt;br /&gt;
method: 'POST',&lt;br /&gt;
data: { team_id: teamId, assignment_id: assignmentId, comments }&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
const acceptJoinTeamRequest = (requestId: number) =&amp;gt;&lt;br /&gt;
acceptRequestAPI.sendRequest({&lt;br /&gt;
url: `/join_team_requests/accept/${requestId}`,&lt;br /&gt;
method: 'POST'&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
const declineJoinTeamRequest = (requestId: number) =&amp;gt;&lt;br /&gt;
declineRequestAPI.sendRequest({&lt;br /&gt;
url: `/join_team_requests/decline/${requestId}`,&lt;br /&gt;
method: 'POST'&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
const fetchTeamRequests = (teamId: number) =&amp;gt;&lt;br /&gt;
fetchTeamRequestsAPI.sendRequest({&lt;br /&gt;
url: `/join_team_requests/team/${teamId}`&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
const fetchAdvertisements = (assignmentId: number) =&amp;gt;&lt;br /&gt;
fetchAdvertisementsAPI.sendRequest({&lt;br /&gt;
url: `/signed_up_teams/advertisements/${assignmentId}`&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
createJoinTeamRequest,&lt;br /&gt;
acceptJoinTeamRequest,&lt;br /&gt;
declineJoinTeamRequest,&lt;br /&gt;
fetchTeamRequests,&lt;br /&gt;
fetchAdvertisements,&lt;br /&gt;
createRequestAPI,&lt;br /&gt;
acceptRequestAPI,&lt;br /&gt;
declineRequestAPI,&lt;br /&gt;
fetchTeamRequestsAPI,&lt;br /&gt;
fetchAdvertisementsAPI&lt;br /&gt;
};&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementation Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Phase 1: Backend Refactoring ===&lt;br /&gt;
&lt;br /&gt;
# '''Refactor action_allowed? method'''&lt;br /&gt;
## Update `Api::V1::JoinTeamRequestsController#action_allowed?` to handle all actions&lt;br /&gt;
## Remove individual privilege checks from `index` method&lt;br /&gt;
## Ensure all actions go through the centralized check&lt;br /&gt;
&lt;br /&gt;
# '''Add accept method'''&lt;br /&gt;
## Implement `accept` method with team full validation&lt;br /&gt;
## Add transaction handling for atomic operations&lt;br /&gt;
## Update request status to ACCEPTED&lt;br /&gt;
## Add participant to team using `team.add_member`&lt;br /&gt;
&lt;br /&gt;
# '''Add team_requests method'''&lt;br /&gt;
## Implement method to fetch requests for a team&lt;br /&gt;
## Add authorization check (user must be team member)&lt;br /&gt;
## Include participant and user data in response&lt;br /&gt;
&lt;br /&gt;
# '''Add advertisements method to SignedUpTeamsController'''&lt;br /&gt;
## Implement method to fetch all advertisements for an assignment&lt;br /&gt;
## Join with teams and sign_up_topics&lt;br /&gt;
## Return formatted advertisement data&lt;br /&gt;
&lt;br /&gt;
# '''Update JoinTeamRequest model'''&lt;br /&gt;
## Add `belongs_to :team` association&lt;br /&gt;
## Add scopes for filtering&lt;br /&gt;
## Update validations&lt;br /&gt;
&lt;br /&gt;
# '''Update routes'''&lt;br /&gt;
## Add routes for new endpoints&lt;br /&gt;
## Ensure RESTful conventions&lt;br /&gt;
&lt;br /&gt;
=== Phase 2: Frontend - Signup Sheet ===&lt;br /&gt;
&lt;br /&gt;
# '''Create SignupSheet component (if not exists)'''&lt;br /&gt;
## Display topics for an assignment&lt;br /&gt;
## Fetch advertisements for the assignment&lt;br /&gt;
## Map advertisements to topics&lt;br /&gt;
## Display trumpet icon for topics with advertisements&lt;br /&gt;
&lt;br /&gt;
# '''Create JoinTeamRequestModal component'''&lt;br /&gt;
## Design modal UI&lt;br /&gt;
## Implement form with comments field&lt;br /&gt;
## Add submit handler&lt;br /&gt;
## Handle success/error states&lt;br /&gt;
&lt;br /&gt;
# '''Integrate modal with SignupSheet'''&lt;br /&gt;
## Add click handler for topics with advertisements&lt;br /&gt;
## Open modal with advertisement details&lt;br /&gt;
## Handle modal close&lt;br /&gt;
&lt;br /&gt;
=== Phase 3: Frontend - StudentTeamView ===&lt;br /&gt;
&lt;br /&gt;
# '''Add Received Requests section'''&lt;br /&gt;
## Create section similar to &amp;quot;Received Invitations&amp;quot;&lt;br /&gt;
## Fetch join team requests for current team&lt;br /&gt;
## Display requests in table format&lt;br /&gt;
&lt;br /&gt;
# '''Implement approve/decline functionality'''&lt;br /&gt;
## Add approve button handler&lt;br /&gt;
## Add decline button handler&lt;br /&gt;
## Check team full status before allowing approve&lt;br /&gt;
## Update UI after actions&lt;br /&gt;
&lt;br /&gt;
# '''Add useJoinTeamRequest hook'''&lt;br /&gt;
## Create hook file&lt;br /&gt;
## Implement all API methods&lt;br /&gt;
## Export hook for use in components&lt;br /&gt;
&lt;br /&gt;
=== Phase 4: Integration and Testing ===&lt;br /&gt;
&lt;br /&gt;
# '''End-to-end testing'''&lt;br /&gt;
## Test advertisement creation → request creation → approval flow&lt;br /&gt;
## Test decline flow&lt;br /&gt;
## Test team full validation&lt;br /&gt;
## Test authorization checks&lt;br /&gt;
&lt;br /&gt;
# '''Unit testing'''&lt;br /&gt;
## Test controller methods&lt;br /&gt;
## Test model validations&lt;br /&gt;
## Test frontend components&lt;br /&gt;
&lt;br /&gt;
# '''Integration testing'''&lt;br /&gt;
## Test API endpoints&lt;br /&gt;
## Test frontend-backend integration&lt;br /&gt;
## Test error handling&lt;br /&gt;
&lt;br /&gt;
== Files Changed/Added ==&lt;br /&gt;
&lt;br /&gt;
=== Backend Files ===&lt;br /&gt;
&lt;br /&gt;
'''Modified:'''&lt;br /&gt;
&lt;br /&gt;
- `app/controllers/api/v1/join_team_requests_controller.rb` - Refactor action_allowed?, add accept and team_requests methods&lt;br /&gt;
- `app/controllers/api/v1/signed_up_teams_controller.rb` - Add advertisements method&lt;br /&gt;
- `app/models/join_team_request.rb` - Add associations and scopes&lt;br /&gt;
- `config/routes.rb` - Add new routes&lt;br /&gt;
&lt;br /&gt;
'''Added:'''&lt;br /&gt;
&lt;br /&gt;
- `spec/requests/api/v1/join_team_requests_spec.rb` - Request specs for new methods&lt;br /&gt;
- `spec/models/join_team_request_spec.rb` - Model specs&lt;br /&gt;
&lt;br /&gt;
=== Frontend Files ===&lt;br /&gt;
&lt;br /&gt;
'''Modified:'''&lt;br /&gt;
&lt;br /&gt;
- `src/pages/Student Teams/StudentTeamView.tsx` - Add Received Requests section&lt;br /&gt;
- `src/hooks/useStudentTeam.ts` - Add join team request methods (or create new hook)&lt;br /&gt;
&lt;br /&gt;
'''Added:'''&lt;br /&gt;
&lt;br /&gt;
- `src/pages/SignUpSheet/SignUpSheet.tsx` - Signup sheet component with advertisement indicators&lt;br /&gt;
- `src/pages/SignUpSheet/JoinTeamRequestModal.tsx` - Modal for creating join team requests&lt;br /&gt;
- `src/hooks/useJoinTeamRequest.ts` - Hook for join team request API calls&lt;br /&gt;
- `src/pages/SignUpSheet/SignUpSheet.module.css` - Styles for signup sheet&lt;br /&gt;
- `src/pages/SignUpSheet/JoinTeamRequestModal.module.css` - Styles for modal&lt;br /&gt;
&lt;br /&gt;
== Testing Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Backend Testing ===&lt;br /&gt;
&lt;br /&gt;
==== Unit Tests ====&lt;br /&gt;
&lt;br /&gt;
# '''JoinTeamRequestsController Tests'''&lt;br /&gt;
## Test action_allowed? for different actions and user roles&lt;br /&gt;
## Test accept method with valid request&lt;br /&gt;
## Test accept method when team is full&lt;br /&gt;
## Test accept method when participant already on team&lt;br /&gt;
## Test team_requests method authorization&lt;br /&gt;
## Test team_requests method returns correct data&lt;br /&gt;
&lt;br /&gt;
# '''SignedUpTeamsController Tests'''&lt;br /&gt;
## Test advertisements method returns correct data&lt;br /&gt;
## Test advertisements method filters correctly&lt;br /&gt;
&lt;br /&gt;
# '''JoinTeamRequest Model Tests'''&lt;br /&gt;
## Test associations&lt;br /&gt;
## Test validations&lt;br /&gt;
## Test scopes&lt;br /&gt;
&lt;br /&gt;
==== Integration Tests ====&lt;br /&gt;
&lt;br /&gt;
# '''End-to-End Flow Tests'''&lt;br /&gt;
## Create advertisement → Create join request → Accept request&lt;br /&gt;
## Create advertisement → Create join request → Decline request&lt;br /&gt;
## Test team full validation prevents acceptance&lt;br /&gt;
## Test authorization prevents unauthorized access&lt;br /&gt;
&lt;br /&gt;
=== Frontend Testing ===&lt;br /&gt;
&lt;br /&gt;
==== Component Tests ====&lt;br /&gt;
&lt;br /&gt;
# '''SignUpSheet Component'''&lt;br /&gt;
## Test advertisement indicators display correctly&lt;br /&gt;
## Test modal opens on click&lt;br /&gt;
## Test data fetching&lt;br /&gt;
&lt;br /&gt;
# '''JoinTeamRequestModal Component'''&lt;br /&gt;
## Test form submission&lt;br /&gt;
## Test validation&lt;br /&gt;
## Test success/error handling&lt;br /&gt;
&lt;br /&gt;
# '''StudentTeamView Component'''&lt;br /&gt;
## Test Received Requests section displays&lt;br /&gt;
## Test approve functionality&lt;br /&gt;
## Test decline functionality&lt;br /&gt;
## Test team full validation&lt;br /&gt;
&lt;br /&gt;
==== Integration Tests ====&lt;br /&gt;
&lt;br /&gt;
# '''API Integration'''&lt;br /&gt;
## Test all API calls work correctly&lt;br /&gt;
## Test error handling&lt;br /&gt;
## Test loading states&lt;br /&gt;
&lt;br /&gt;
== Edge Cases and Error Handling ==&lt;br /&gt;
&lt;br /&gt;
=== Backend Edge Cases ===&lt;br /&gt;
&lt;br /&gt;
# '''Team Full Validation'''&lt;br /&gt;
- Check team capacity before accepting request&lt;br /&gt;
- Return appropriate error message&lt;br /&gt;
- Prevent race conditions with database transactions&lt;br /&gt;
&lt;br /&gt;
# '''Authorization'''&lt;br /&gt;
- Verify user is team member before showing requests&lt;br /&gt;
- Verify user is student before creating requests&lt;br /&gt;
- Verify user is administrator before viewing all requests&lt;br /&gt;
&lt;br /&gt;
# '''Duplicate Requests'''&lt;br /&gt;
- Prevent creating duplicate requests from same participant&lt;br /&gt;
- Handle case where participant already on team&lt;br /&gt;
&lt;br /&gt;
# '''Concurrent Modifications'''&lt;br /&gt;
- Use transactions for atomic operations&lt;br /&gt;
- Handle race conditions in team membership updates&lt;br /&gt;
&lt;br /&gt;
=== Frontend Edge Cases ===&lt;br /&gt;
&lt;br /&gt;
# '''Network Errors'''&lt;br /&gt;
- Display appropriate error messages&lt;br /&gt;
- Handle timeout scenarios&lt;br /&gt;
- Provide retry mechanisms&lt;br /&gt;
&lt;br /&gt;
# '''Empty States'''&lt;br /&gt;
- Show appropriate messages when no advertisements exist&lt;br /&gt;
- Show appropriate messages when no requests exist&lt;br /&gt;
&lt;br /&gt;
# '''Loading States'''&lt;br /&gt;
- Display loading indicators during API calls&lt;br /&gt;
- Prevent multiple simultaneous requests&lt;br /&gt;
&lt;br /&gt;
# '''Form Validation'''&lt;br /&gt;
- Validate required fields&lt;br /&gt;
- Provide user feedback for errors&lt;br /&gt;
&lt;br /&gt;
== Security Considerations ==&lt;br /&gt;
&lt;br /&gt;
# '''Authorization Checks'''&lt;br /&gt;
- All endpoints must verify user permissions&lt;br /&gt;
- Team members can only see requests for their team&lt;br /&gt;
- Students can only create requests for themselves&lt;br /&gt;
&lt;br /&gt;
# '''Input Validation'''&lt;br /&gt;
- Sanitize all user inputs&lt;br /&gt;
- Validate team_id and assignment_id parameters&lt;br /&gt;
- Prevent SQL injection through parameterized queries&lt;br /&gt;
&lt;br /&gt;
# '''Rate Limiting'''&lt;br /&gt;
- Consider rate limiting for request creation&lt;br /&gt;
- Prevent spam requests&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
- Expertiza Wiki: E2252. Refactor auth controller.rb &amp;amp; password retrieval controller.rb&lt;br /&gt;
- Rails API Documentation&lt;br /&gt;
- React Router Documentation&lt;br /&gt;
- Expertiza Codebase: Existing invitation and team management implementations&lt;/div&gt;</summary>
		<author><name>Vpatel29</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:ViewAdv.png&amp;diff=167107</id>
		<title>File:ViewAdv.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:ViewAdv.png&amp;diff=167107"/>
		<updated>2025-11-11T02:25:54Z</updated>

		<summary type="html">&lt;p&gt;Vpatel29: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Vpatel29</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:TrumpetSign.png&amp;diff=167106</id>
		<title>File:TrumpetSign.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:TrumpetSign.png&amp;diff=167106"/>
		<updated>2025-11-11T02:25:47Z</updated>

		<summary type="html">&lt;p&gt;Vpatel29: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Vpatel29</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:JoinReq.png&amp;diff=167105</id>
		<title>File:JoinReq.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:JoinReq.png&amp;diff=167105"/>
		<updated>2025-11-11T02:25:40Z</updated>

		<summary type="html">&lt;p&gt;Vpatel29: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Vpatel29</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:AllReq.png&amp;diff=167104</id>
		<title>File:AllReq.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:AllReq.png&amp;diff=167104"/>
		<updated>2025-11-11T02:25:32Z</updated>

		<summary type="html">&lt;p&gt;Vpatel29: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Vpatel29</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=File:All_req.png&amp;diff=167102</id>
		<title>File:All req.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=File:All_req.png&amp;diff=167102"/>
		<updated>2025-11-11T02:21:34Z</updated>

		<summary type="html">&lt;p&gt;Vpatel29: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Vpatel29</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025_-_E2565._Integration_of_JoinTeamRequests&amp;diff=167099</id>
		<title>CSC/ECE 517 Fall 2025 - E2565. Integration of JoinTeamRequests</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025_-_E2565._Integration_of_JoinTeamRequests&amp;diff=167099"/>
		<updated>2025-11-11T02:14:32Z</updated>

		<summary type="html">&lt;p&gt;Vpatel29: Created page with &amp;quot;= E2565. Integration of JoinTeamRequests =  == Overview ==  This document describes the design and implementation plan for integrating JoinTeamRequests functionality in Expertiza. The feature enables students to respond to teammate advertisements by creating join team requests, which topic holders can then approve or decline. This integration will complete the teammate advertisement workflow by connecting the advertisement creation (already implemented) with the join tea...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;= E2565. Integration of JoinTeamRequests =&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
This document describes the design and implementation plan for integrating JoinTeamRequests functionality in Expertiza. The feature enables students to respond to teammate advertisements by creating join team requests, which topic holders can then approve or decline. This integration will complete the teammate advertisement workflow by connecting the advertisement creation (already implemented) with the join team request flow.&lt;br /&gt;
&lt;br /&gt;
=== Problem Statement ===&lt;br /&gt;
&lt;br /&gt;
Currently, Expertiza supports teammate advertisements for assignments with topics. Topic holders can create advertisements on the &amp;quot;Your Team&amp;quot; page. However, the complete flow for responding to advertisements and managing join team requests is not fully integrated. The following gaps exist:&lt;br /&gt;
&lt;br /&gt;
# The join_team_requests_controller has action privilege checks scattered across methods instead of using a centralized `action_allowed?` method&lt;br /&gt;
&lt;br /&gt;
# There is no frontend UI for viewing advertisements on the Signup Sheet page&lt;br /&gt;
&lt;br /&gt;
# There is no UI for creating join team requests when responding to advertisements&lt;br /&gt;
&lt;br /&gt;
# The &amp;quot;Received Requests&amp;quot; section is missing from the StudentTeamView page&lt;br /&gt;
&lt;br /&gt;
# There is no method to accept join team requests (only decline exists)&lt;br /&gt;
&lt;br /&gt;
# The controller needs better integration with the frontend&lt;br /&gt;
&lt;br /&gt;
=== Goals ===&lt;br /&gt;
&lt;br /&gt;
# Refactor the join_team_requests_controller to use a single `action_allowed?` method for privilege checking&lt;br /&gt;
&lt;br /&gt;
# Add a trumpet icon on the Signup Sheet page to indicate when advertisements exist for topics&lt;br /&gt;
&lt;br /&gt;
# Create a frontend UI for viewing advertisements and creating join team requests&lt;br /&gt;
&lt;br /&gt;
# Add a &amp;quot;Received Requests&amp;quot; section to StudentTeamView.tsx for managing incoming join team requests&lt;br /&gt;
&lt;br /&gt;
# Implement an accept method for join team requests&lt;br /&gt;
&lt;br /&gt;
# Ensure proper validation that teams cannot accept requests when full&lt;br /&gt;
&lt;br /&gt;
# Conduct comprehensive testing of the entire flow&lt;br /&gt;
&lt;br /&gt;
== Design ==&lt;br /&gt;
&lt;br /&gt;
=== Backend Design ===&lt;br /&gt;
&lt;br /&gt;
==== Controller Refactoring ====&lt;br /&gt;
&lt;br /&gt;
The `Api::V1::JoinTeamRequestsController` currently has privilege checks scattered across methods:&lt;br /&gt;
&lt;br /&gt;
- `index` method checks for administrator role directly&lt;br /&gt;
- `action_allowed?` only checks if user is a student&lt;br /&gt;
&lt;br /&gt;
'''Refactored Design:'''&lt;br /&gt;
&lt;br /&gt;
The `action_allowed?` method will be enhanced to handle different actions based on the action being performed:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
def action_allowed?&lt;br /&gt;
  case action_name.to_sym&lt;br /&gt;
  when :index&lt;br /&gt;
    @current_user.administrator?&lt;br /&gt;
  when :create, :show, :update, :destroy, :decline, :accept&lt;br /&gt;
    @current_user.student?&lt;br /&gt;
  else&lt;br /&gt;
    false&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All methods will rely on this centralized privilege check, removing individual checks from methods like `index`.&lt;br /&gt;
&lt;br /&gt;
==== New Methods ====&lt;br /&gt;
&lt;br /&gt;
'''1. Accept Method'''&lt;br /&gt;
&lt;br /&gt;
Add a new `accept` method to handle accepting join team requests:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
# PATCH/PUT api/v1/join_team_requests/:id/accept&lt;br /&gt;
# Accepts a join team request and adds the participant to the team&lt;br /&gt;
def accept&lt;br /&gt;
  team = @join_team_request.team&lt;br /&gt;
  &lt;br /&gt;
  # Check if team is full&lt;br /&gt;
  if team.full?&lt;br /&gt;
    return render json: { error: 'This team is full.' }, status: :unprocessable_entity&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  # Check if participant is already on the team&lt;br /&gt;
  if team.participants.include?(@join_team_request.participant)&lt;br /&gt;
    return render json: { error: 'Participant already belongs to the team' }, status: :unprocessable_entity&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  ActiveRecord::Base.transaction do&lt;br /&gt;
    # Add participant to team&lt;br /&gt;
    result = team.add_member(@join_team_request.participant)&lt;br /&gt;
    &lt;br /&gt;
    if result[:success]&lt;br /&gt;
      # Update request status&lt;br /&gt;
      @join_team_request.update!(reply_status: ACCEPTED)&lt;br /&gt;
      render json: { message: 'JoinTeamRequest accepted successfully', join_team_request: @join_team_request }, status: :ok&lt;br /&gt;
    else&lt;br /&gt;
      render json: { error: result[:error] }, status: :unprocessable_entity&lt;br /&gt;
      raise ActiveRecord::Rollback&lt;br /&gt;
    end&lt;br /&gt;
  end&lt;br /&gt;
rescue =&amp;gt; e&lt;br /&gt;
  render json: { error: &amp;quot;Failed to accept request: #{e.message}&amp;quot; }, status: :unprocessable_entity&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''2. Get Join Team Requests for Team'''&lt;br /&gt;
&lt;br /&gt;
Add a method to fetch all join team requests for a specific team (for the &amp;quot;Received Requests&amp;quot; section):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
# GET api/v1/join_team_requests/team/:team_id&lt;br /&gt;
# Gets all join team requests for a specific team&lt;br /&gt;
def team_requests&lt;br /&gt;
  team = Team.find(params[:team_id])&lt;br /&gt;
  &lt;br /&gt;
  # Verify current user is a member of the team&lt;br /&gt;
  unless team.participants.exists?(user_id: @current_user.id)&lt;br /&gt;
    return render json: { error: 'Unauthorized' }, status: :unauthorized&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  join_team_requests = JoinTeamRequest.where(team_id: params[:team_id])&lt;br /&gt;
    .includes(:participant =&amp;gt; :user)&lt;br /&gt;
    .order(created_at: :desc)&lt;br /&gt;
  &lt;br /&gt;
  render json: join_team_requests, status: :ok&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''3. Get Advertisements for Assignment'''&lt;br /&gt;
&lt;br /&gt;
Add a method to fetch all advertisements for an assignment (for the Signup Sheet page):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
# GET api/v1/signed_up_teams/advertisements/:assignment_id&lt;br /&gt;
# Gets all advertisements for an assignment&lt;br /&gt;
def advertisements&lt;br /&gt;
  assignment = Assignment.find(params[:assignment_id])&lt;br /&gt;
  signed_up_teams = SignedUpTeam.joins(:team, :sign_up_topic)&lt;br /&gt;
    .where(sign_up_topics: { assignment_id: params[:assignment_id] })&lt;br /&gt;
    .where(advertise_for_partner: true)&lt;br /&gt;
    .includes(:team, :sign_up_topic)&lt;br /&gt;
  &lt;br /&gt;
  advertisements = signed_up_teams.map do |sut|&lt;br /&gt;
    {&lt;br /&gt;
      id: sut.id,&lt;br /&gt;
      team_id: sut.team_id,&lt;br /&gt;
      team_name: sut.team.name,&lt;br /&gt;
      topic_id: sut.sign_up_topic_id,&lt;br /&gt;
      topic_name: sut.sign_up_topic.topic_name,&lt;br /&gt;
      comments_for_advertisement: sut.comments_for_advertisement,&lt;br /&gt;
      created_at: sut.created_at&lt;br /&gt;
    }&lt;br /&gt;
  end&lt;br /&gt;
  &lt;br /&gt;
  render json: advertisements, status: :ok&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Model Updates ====&lt;br /&gt;
&lt;br /&gt;
The `JoinTeamRequest` model needs to establish proper associations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
class JoinTeamRequest &amp;lt; ApplicationRecord&lt;br /&gt;
  belongs_to :team&lt;br /&gt;
  belongs_to :participant&lt;br /&gt;
  &lt;br /&gt;
  ACCEPTED_STATUSES = %w[ACCEPTED DECLINED PENDING]&lt;br /&gt;
  validates :reply_status, inclusion: { in: ACCEPTED_STATUSES }&lt;br /&gt;
  &lt;br /&gt;
  scope :pending, -&amp;gt; { where(reply_status: 'PENDING') }&lt;br /&gt;
  scope :for_team, -&amp;gt;(team_id) { where(team_id: team_id) }&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== Routes Updates ====&lt;br /&gt;
&lt;br /&gt;
Add new routes for the additional endpoints:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;ruby&amp;quot;&amp;gt;&lt;br /&gt;
resources :join_team_requests do&lt;br /&gt;
  collection do&lt;br /&gt;
    get 'team/:team_id', to: 'join_team_requests#team_requests'&lt;br /&gt;
    post 'decline/:id', to: 'join_team_requests#decline'&lt;br /&gt;
    post 'accept/:id', to: 'join_team_requests#accept'&lt;br /&gt;
  end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
resources :signed_up_teams do&lt;br /&gt;
collection do&lt;br /&gt;
get 'advertisements/:assignment_id', to: 'signed_up_teams#advertisements'&lt;br /&gt;
end&lt;br /&gt;
member do&lt;br /&gt;
post :create_advertisement&lt;br /&gt;
patch :update_advertisement&lt;br /&gt;
delete :remove_advertisement&lt;br /&gt;
end&lt;br /&gt;
end&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Frontend Design ===&lt;br /&gt;
&lt;br /&gt;
==== Signup Sheet Page Enhancement ====&lt;br /&gt;
&lt;br /&gt;
Create a new component or enhance existing signup sheet to display advertisements:&lt;br /&gt;
&lt;br /&gt;
'''Component: SignupSheet.tsx'''&lt;br /&gt;
&lt;br /&gt;
This component will:&lt;br /&gt;
&lt;br /&gt;
- Display all topics for an assignment&lt;br /&gt;
- Show a trumpet icon (🔔) next to topics that have advertisements&lt;br /&gt;
- Allow users to click on topics with advertisements to view details&lt;br /&gt;
- Provide a modal/dialog to view advertisement details and create a join team request&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
interface Advertisement {&lt;br /&gt;
  id: number;&lt;br /&gt;
  team_id: number;&lt;br /&gt;
  team_name: string;&lt;br /&gt;
  topic_id: number;&lt;br /&gt;
  topic_name: string;&lt;br /&gt;
  comments_for_advertisement: string;&lt;br /&gt;
  created_at: string;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
interface SignUpTopic {&lt;br /&gt;
id: number;&lt;br /&gt;
topic_name: string;&lt;br /&gt;
topic_identifier: string;&lt;br /&gt;
max_choosers: number;&lt;br /&gt;
description?: string;&lt;br /&gt;
has_advertisement?: boolean;&lt;br /&gt;
advertisement?: Advertisement;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The UI will show:&lt;br /&gt;
&lt;br /&gt;
- A table/list of topics&lt;br /&gt;
- Trumpet icon indicator for topics with advertisements&lt;br /&gt;
- Click handler to open advertisement details modal&lt;br /&gt;
&lt;br /&gt;
==== Join Team Request Modal ====&lt;br /&gt;
&lt;br /&gt;
Create a modal component for creating join team requests:&lt;br /&gt;
&lt;br /&gt;
'''Component: JoinTeamRequestModal.tsx'''&lt;br /&gt;
&lt;br /&gt;
This modal will:&lt;br /&gt;
&lt;br /&gt;
- Display advertisement details (team name, topic, desired qualifications)&lt;br /&gt;
- Provide a text area for comments (optional)&lt;br /&gt;
- Show a &amp;quot;Send Request&amp;quot; button&lt;br /&gt;
- Handle form submission and API calls&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
interface JoinTeamRequestModalProps {&lt;br /&gt;
  show: boolean;&lt;br /&gt;
  onHide: () =&amp;gt; void;&lt;br /&gt;
  advertisement: Advertisement;&lt;br /&gt;
  assignmentId: number;&lt;br /&gt;
  onSuccess: () =&amp;gt; void;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==== StudentTeamView Enhancement ====&lt;br /&gt;
&lt;br /&gt;
Add a &amp;quot;Received Requests&amp;quot; section to `StudentTeamView.tsx`:&lt;br /&gt;
&lt;br /&gt;
'''Section: Received Join Team Requests'''&lt;br /&gt;
&lt;br /&gt;
This section will:&lt;br /&gt;
&lt;br /&gt;
- Display all pending join team requests for the current team&lt;br /&gt;
- Show request details: requester name, email, comments, date&lt;br /&gt;
- Provide &amp;quot;Approve&amp;quot; and &amp;quot;Decline&amp;quot; buttons for each request&lt;br /&gt;
- Disable approve button if team is full&lt;br /&gt;
- Show status for non-pending requests&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
interface JoinTeamRequest {&lt;br /&gt;
  id: number;&lt;br /&gt;
  participant_id: number;&lt;br /&gt;
  team_id: number;&lt;br /&gt;
  comments: string;&lt;br /&gt;
  reply_status: 'PENDING' | 'ACCEPTED' | 'DECLINED';&lt;br /&gt;
  created_at: string;&lt;br /&gt;
  participant: {&lt;br /&gt;
    id: number;&lt;br /&gt;
    user: {&lt;br /&gt;
      id: number;&lt;br /&gt;
      name: string;&lt;br /&gt;
      full_name: string;&lt;br /&gt;
      email: string;&lt;br /&gt;
    };&lt;br /&gt;
  };&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The UI structure will be similar to the existing &amp;quot;Received Invitations&amp;quot; section, with:&lt;br /&gt;
&lt;br /&gt;
- Table displaying request information&lt;br /&gt;
- Action buttons (Approve/Decline) for pending requests&lt;br /&gt;
- Status display for processed requests&lt;br /&gt;
&lt;br /&gt;
==== API Hooks ====&lt;br /&gt;
&lt;br /&gt;
Create or extend hooks for join team requests:&lt;br /&gt;
&lt;br /&gt;
'''File: hooks/useJoinTeamRequest.ts'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;typescript&amp;quot;&amp;gt;&lt;br /&gt;
export const useJoinTeamRequest = () =&amp;gt; {&lt;br /&gt;
  const createRequestAPI = useAPI();&lt;br /&gt;
  const acceptRequestAPI = useAPI();&lt;br /&gt;
  const declineRequestAPI = useAPI();&lt;br /&gt;
  const fetchTeamRequestsAPI = useAPI();&lt;br /&gt;
  const fetchAdvertisementsAPI = useAPI();&lt;br /&gt;
&lt;br /&gt;
const createJoinTeamRequest = (teamId: number, assignmentId: number, comments?: string) =&amp;gt;&lt;br /&gt;
createRequestAPI.sendRequest({&lt;br /&gt;
url: `/join_team_requests`,&lt;br /&gt;
method: 'POST',&lt;br /&gt;
data: { team_id: teamId, assignment_id: assignmentId, comments }&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
const acceptJoinTeamRequest = (requestId: number) =&amp;gt;&lt;br /&gt;
acceptRequestAPI.sendRequest({&lt;br /&gt;
url: `/join_team_requests/accept/${requestId}`,&lt;br /&gt;
method: 'POST'&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
const declineJoinTeamRequest = (requestId: number) =&amp;gt;&lt;br /&gt;
declineRequestAPI.sendRequest({&lt;br /&gt;
url: `/join_team_requests/decline/${requestId}`,&lt;br /&gt;
method: 'POST'&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
const fetchTeamRequests = (teamId: number) =&amp;gt;&lt;br /&gt;
fetchTeamRequestsAPI.sendRequest({&lt;br /&gt;
url: `/join_team_requests/team/${teamId}`&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
const fetchAdvertisements = (assignmentId: number) =&amp;gt;&lt;br /&gt;
fetchAdvertisementsAPI.sendRequest({&lt;br /&gt;
url: `/signed_up_teams/advertisements/${assignmentId}`&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
return {&lt;br /&gt;
createJoinTeamRequest,&lt;br /&gt;
acceptJoinTeamRequest,&lt;br /&gt;
declineJoinTeamRequest,&lt;br /&gt;
fetchTeamRequests,&lt;br /&gt;
fetchAdvertisements,&lt;br /&gt;
createRequestAPI,&lt;br /&gt;
acceptRequestAPI,&lt;br /&gt;
declineRequestAPI,&lt;br /&gt;
fetchTeamRequestsAPI,&lt;br /&gt;
fetchAdvertisementsAPI&lt;br /&gt;
};&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementation Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Phase 1: Backend Refactoring ===&lt;br /&gt;
&lt;br /&gt;
# '''Refactor action_allowed? method'''&lt;br /&gt;
&lt;br /&gt;
## Update `Api::V1::JoinTeamRequestsController#action_allowed?` to handle all actions&lt;br /&gt;
&lt;br /&gt;
## Remove individual privilege checks from `index` method&lt;br /&gt;
&lt;br /&gt;
## Ensure all actions go through the centralized check&lt;br /&gt;
&lt;br /&gt;
# '''Add accept method'''&lt;br /&gt;
&lt;br /&gt;
## Implement `accept` method with team full validation&lt;br /&gt;
&lt;br /&gt;
## Add transaction handling for atomic operations&lt;br /&gt;
&lt;br /&gt;
## Update request status to ACCEPTED&lt;br /&gt;
&lt;br /&gt;
## Add participant to team using `team.add_member`&lt;br /&gt;
&lt;br /&gt;
# '''Add team_requests method'''&lt;br /&gt;
&lt;br /&gt;
## Implement method to fetch requests for a team&lt;br /&gt;
&lt;br /&gt;
## Add authorization check (user must be team member)&lt;br /&gt;
&lt;br /&gt;
## Include participant and user data in response&lt;br /&gt;
&lt;br /&gt;
# '''Add advertisements method to SignedUpTeamsController'''&lt;br /&gt;
&lt;br /&gt;
## Implement method to fetch all advertisements for an assignment&lt;br /&gt;
&lt;br /&gt;
## Join with teams and sign_up_topics&lt;br /&gt;
&lt;br /&gt;
## Return formatted advertisement data&lt;br /&gt;
&lt;br /&gt;
# '''Update JoinTeamRequest model'''&lt;br /&gt;
&lt;br /&gt;
## Add `belongs_to :team` association&lt;br /&gt;
&lt;br /&gt;
## Add scopes for filtering&lt;br /&gt;
&lt;br /&gt;
## Update validations&lt;br /&gt;
&lt;br /&gt;
# '''Update routes'''&lt;br /&gt;
&lt;br /&gt;
## Add routes for new endpoints&lt;br /&gt;
&lt;br /&gt;
## Ensure RESTful conventions&lt;br /&gt;
&lt;br /&gt;
=== Phase 2: Frontend - Signup Sheet ===&lt;br /&gt;
&lt;br /&gt;
# '''Create SignupSheet component (if not exists)'''&lt;br /&gt;
&lt;br /&gt;
## Display topics for an assignment&lt;br /&gt;
&lt;br /&gt;
## Fetch advertisements for the assignment&lt;br /&gt;
&lt;br /&gt;
## Map advertisements to topics&lt;br /&gt;
&lt;br /&gt;
## Display trumpet icon for topics with advertisements&lt;br /&gt;
&lt;br /&gt;
# '''Create JoinTeamRequestModal component'''&lt;br /&gt;
&lt;br /&gt;
## Design modal UI&lt;br /&gt;
&lt;br /&gt;
## Implement form with comments field&lt;br /&gt;
&lt;br /&gt;
## Add submit handler&lt;br /&gt;
&lt;br /&gt;
## Handle success/error states&lt;br /&gt;
&lt;br /&gt;
# '''Integrate modal with SignupSheet'''&lt;br /&gt;
&lt;br /&gt;
## Add click handler for topics with advertisements&lt;br /&gt;
&lt;br /&gt;
## Open modal with advertisement details&lt;br /&gt;
&lt;br /&gt;
## Handle modal close&lt;br /&gt;
&lt;br /&gt;
=== Phase 3: Frontend - StudentTeamView ===&lt;br /&gt;
&lt;br /&gt;
# '''Add Received Requests section'''&lt;br /&gt;
&lt;br /&gt;
## Create section similar to &amp;quot;Received Invitations&amp;quot;&lt;br /&gt;
&lt;br /&gt;
## Fetch join team requests for current team&lt;br /&gt;
&lt;br /&gt;
## Display requests in table format&lt;br /&gt;
&lt;br /&gt;
# '''Implement approve/decline functionality'''&lt;br /&gt;
&lt;br /&gt;
## Add approve button handler&lt;br /&gt;
&lt;br /&gt;
## Add decline button handler&lt;br /&gt;
&lt;br /&gt;
## Check team full status before allowing approve&lt;br /&gt;
&lt;br /&gt;
## Update UI after actions&lt;br /&gt;
&lt;br /&gt;
# '''Add useJoinTeamRequest hook'''&lt;br /&gt;
&lt;br /&gt;
## Create hook file&lt;br /&gt;
&lt;br /&gt;
## Implement all API methods&lt;br /&gt;
&lt;br /&gt;
## Export hook for use in components&lt;br /&gt;
&lt;br /&gt;
=== Phase 4: Integration and Testing ===&lt;br /&gt;
&lt;br /&gt;
# '''End-to-end testing'''&lt;br /&gt;
&lt;br /&gt;
## Test advertisement creation → request creation → approval flow&lt;br /&gt;
&lt;br /&gt;
## Test decline flow&lt;br /&gt;
&lt;br /&gt;
## Test team full validation&lt;br /&gt;
&lt;br /&gt;
## Test authorization checks&lt;br /&gt;
&lt;br /&gt;
# '''Unit testing'''&lt;br /&gt;
&lt;br /&gt;
## Test controller methods&lt;br /&gt;
&lt;br /&gt;
## Test model validations&lt;br /&gt;
&lt;br /&gt;
## Test frontend components&lt;br /&gt;
&lt;br /&gt;
# '''Integration testing'''&lt;br /&gt;
&lt;br /&gt;
## Test API endpoints&lt;br /&gt;
&lt;br /&gt;
## Test frontend-backend integration&lt;br /&gt;
&lt;br /&gt;
## Test error handling&lt;br /&gt;
&lt;br /&gt;
== Files Changed/Added ==&lt;br /&gt;
&lt;br /&gt;
=== Backend Files ===&lt;br /&gt;
&lt;br /&gt;
'''Modified:'''&lt;br /&gt;
&lt;br /&gt;
- `app/controllers/api/v1/join_team_requests_controller.rb` - Refactor action_allowed?, add accept and team_requests methods&lt;br /&gt;
- `app/controllers/api/v1/signed_up_teams_controller.rb` - Add advertisements method&lt;br /&gt;
- `app/models/join_team_request.rb` - Add associations and scopes&lt;br /&gt;
- `config/routes.rb` - Add new routes&lt;br /&gt;
&lt;br /&gt;
'''Added:'''&lt;br /&gt;
&lt;br /&gt;
- `spec/requests/api/v1/join_team_requests_spec.rb` - Request specs for new methods&lt;br /&gt;
- `spec/models/join_team_request_spec.rb` - Model specs&lt;br /&gt;
&lt;br /&gt;
=== Frontend Files ===&lt;br /&gt;
&lt;br /&gt;
'''Modified:'''&lt;br /&gt;
&lt;br /&gt;
- `src/pages/Student Teams/StudentTeamView.tsx` - Add Received Requests section&lt;br /&gt;
- `src/hooks/useStudentTeam.ts` - Add join team request methods (or create new hook)&lt;br /&gt;
&lt;br /&gt;
'''Added:'''&lt;br /&gt;
&lt;br /&gt;
- `src/pages/SignUpSheet/SignUpSheet.tsx` - Signup sheet component with advertisement indicators&lt;br /&gt;
- `src/pages/SignUpSheet/JoinTeamRequestModal.tsx` - Modal for creating join team requests&lt;br /&gt;
- `src/hooks/useJoinTeamRequest.ts` - Hook for join team request API calls&lt;br /&gt;
- `src/pages/SignUpSheet/SignUpSheet.module.css` - Styles for signup sheet&lt;br /&gt;
- `src/pages/SignUpSheet/JoinTeamRequestModal.module.css` - Styles for modal&lt;br /&gt;
&lt;br /&gt;
== Testing Plan ==&lt;br /&gt;
&lt;br /&gt;
=== Backend Testing ===&lt;br /&gt;
&lt;br /&gt;
==== Unit Tests ====&lt;br /&gt;
&lt;br /&gt;
# '''JoinTeamRequestsController Tests'''&lt;br /&gt;
&lt;br /&gt;
## Test action_allowed? for different actions and user roles&lt;br /&gt;
&lt;br /&gt;
## Test accept method with valid request&lt;br /&gt;
&lt;br /&gt;
## Test accept method when team is full&lt;br /&gt;
&lt;br /&gt;
## Test accept method when participant already on team&lt;br /&gt;
&lt;br /&gt;
## Test team_requests method authorization&lt;br /&gt;
&lt;br /&gt;
## Test team_requests method returns correct data&lt;br /&gt;
&lt;br /&gt;
# '''SignedUpTeamsController Tests'''&lt;br /&gt;
&lt;br /&gt;
## Test advertisements method returns correct data&lt;br /&gt;
&lt;br /&gt;
## Test advertisements method filters correctly&lt;br /&gt;
&lt;br /&gt;
# '''JoinTeamRequest Model Tests'''&lt;br /&gt;
&lt;br /&gt;
## Test associations&lt;br /&gt;
&lt;br /&gt;
## Test validations&lt;br /&gt;
&lt;br /&gt;
## Test scopes&lt;br /&gt;
&lt;br /&gt;
==== Integration Tests ====&lt;br /&gt;
&lt;br /&gt;
# '''End-to-End Flow Tests'''&lt;br /&gt;
&lt;br /&gt;
## Create advertisement → Create join request → Accept request&lt;br /&gt;
&lt;br /&gt;
## Create advertisement → Create join request → Decline request&lt;br /&gt;
&lt;br /&gt;
## Test team full validation prevents acceptance&lt;br /&gt;
&lt;br /&gt;
## Test authorization prevents unauthorized access&lt;br /&gt;
&lt;br /&gt;
=== Frontend Testing ===&lt;br /&gt;
&lt;br /&gt;
==== Component Tests ====&lt;br /&gt;
&lt;br /&gt;
# '''SignUpSheet Component'''&lt;br /&gt;
&lt;br /&gt;
## Test advertisement indicators display correctly&lt;br /&gt;
&lt;br /&gt;
## Test modal opens on click&lt;br /&gt;
&lt;br /&gt;
## Test data fetching&lt;br /&gt;
&lt;br /&gt;
# '''JoinTeamRequestModal Component'''&lt;br /&gt;
&lt;br /&gt;
## Test form submission&lt;br /&gt;
&lt;br /&gt;
## Test validation&lt;br /&gt;
&lt;br /&gt;
## Test success/error handling&lt;br /&gt;
&lt;br /&gt;
# '''StudentTeamView Component'''&lt;br /&gt;
&lt;br /&gt;
## Test Received Requests section displays&lt;br /&gt;
&lt;br /&gt;
## Test approve functionality&lt;br /&gt;
&lt;br /&gt;
## Test decline functionality&lt;br /&gt;
&lt;br /&gt;
## Test team full validation&lt;br /&gt;
&lt;br /&gt;
==== Integration Tests ====&lt;br /&gt;
&lt;br /&gt;
# '''API Integration'''&lt;br /&gt;
&lt;br /&gt;
## Test all API calls work correctly&lt;br /&gt;
&lt;br /&gt;
## Test error handling&lt;br /&gt;
&lt;br /&gt;
## Test loading states&lt;br /&gt;
&lt;br /&gt;
== Edge Cases and Error Handling ==&lt;br /&gt;
&lt;br /&gt;
=== Backend Edge Cases ===&lt;br /&gt;
&lt;br /&gt;
# '''Team Full Validation'''&lt;br /&gt;
&lt;br /&gt;
- Check team capacity before accepting request&lt;br /&gt;
- Return appropriate error message&lt;br /&gt;
- Prevent race conditions with database transactions&lt;br /&gt;
&lt;br /&gt;
# '''Authorization'''&lt;br /&gt;
&lt;br /&gt;
- Verify user is team member before showing requests&lt;br /&gt;
- Verify user is student before creating requests&lt;br /&gt;
- Verify user is administrator before viewing all requests&lt;br /&gt;
&lt;br /&gt;
# '''Duplicate Requests'''&lt;br /&gt;
&lt;br /&gt;
- Prevent creating duplicate requests from same participant&lt;br /&gt;
- Handle case where participant already on team&lt;br /&gt;
&lt;br /&gt;
# '''Concurrent Modifications'''&lt;br /&gt;
&lt;br /&gt;
- Use transactions for atomic operations&lt;br /&gt;
- Handle race conditions in team membership updates&lt;br /&gt;
&lt;br /&gt;
=== Frontend Edge Cases ===&lt;br /&gt;
&lt;br /&gt;
# '''Network Errors'''&lt;br /&gt;
&lt;br /&gt;
- Display appropriate error messages&lt;br /&gt;
- Handle timeout scenarios&lt;br /&gt;
- Provide retry mechanisms&lt;br /&gt;
&lt;br /&gt;
# '''Empty States'''&lt;br /&gt;
&lt;br /&gt;
- Show appropriate messages when no advertisements exist&lt;br /&gt;
- Show appropriate messages when no requests exist&lt;br /&gt;
&lt;br /&gt;
# '''Loading States'''&lt;br /&gt;
&lt;br /&gt;
- Display loading indicators during API calls&lt;br /&gt;
- Prevent multiple simultaneous requests&lt;br /&gt;
&lt;br /&gt;
# '''Form Validation'''&lt;br /&gt;
&lt;br /&gt;
- Validate required fields&lt;br /&gt;
- Provide user feedback for errors&lt;br /&gt;
&lt;br /&gt;
== Security Considerations ==&lt;br /&gt;
&lt;br /&gt;
# '''Authorization Checks'''&lt;br /&gt;
&lt;br /&gt;
- All endpoints must verify user permissions&lt;br /&gt;
- Team members can only see requests for their team&lt;br /&gt;
- Students can only create requests for themselves&lt;br /&gt;
&lt;br /&gt;
# '''Input Validation'''&lt;br /&gt;
&lt;br /&gt;
- Sanitize all user inputs&lt;br /&gt;
- Validate team_id and assignment_id parameters&lt;br /&gt;
- Prevent SQL injection through parameterized queries&lt;br /&gt;
&lt;br /&gt;
# '''Rate Limiting'''&lt;br /&gt;
&lt;br /&gt;
- Consider rate limiting for request creation&lt;br /&gt;
- Prevent spam requests&lt;br /&gt;
&lt;br /&gt;
== Future Enhancements ==&lt;br /&gt;
&lt;br /&gt;
# Email notifications when join team requests are created&lt;br /&gt;
&lt;br /&gt;
# Email notifications when requests are approved/declined&lt;br /&gt;
&lt;br /&gt;
# Bulk approve/decline functionality&lt;br /&gt;
&lt;br /&gt;
# Request history and audit trail&lt;br /&gt;
&lt;br /&gt;
# Advanced filtering and search for requests&lt;br /&gt;
&lt;br /&gt;
== References ==&lt;br /&gt;
&lt;br /&gt;
- Expertiza Wiki: E2252. Refactor auth controller.rb &amp;amp; password retrieval controller.rb&lt;br /&gt;
- Rails API Documentation&lt;br /&gt;
- React Router Documentation&lt;br /&gt;
- Expertiza Codebase: Existing invitation and team management implementations&lt;/div&gt;</summary>
		<author><name>Vpatel29</name></author>
	</entry>
	<entry>
		<id>https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025&amp;diff=167098</id>
		<title>CSC/ECE 517 Fall 2025</title>
		<link rel="alternate" type="text/html" href="https://wiki.expertiza.ncsu.edu/index.php?title=CSC/ECE_517_Fall_2025&amp;diff=167098"/>
		<updated>2025-11-11T02:13:19Z</updated>

		<summary type="html">&lt;p&gt;Vpatel29: /* Final Projects */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;* [[CSC/ECE 517 Fall 2025 - E2550. Response hierarchy and responses_controller back end]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2551. Reimplementing SubmittedContentController]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2552. ProjectTopic and SignedUpTeam]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2553.  Heatgrid and Grades Controller (Frontend + Backend)]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2554. Front end for View Submissions Page]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2555. Front end for Participants Page]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2556. Front ends for Create Teams and Assign Reviewers]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2557. Specialized rubrics for different topic types]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2558. Tabbed view for creating and editing assignments]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Final Projects ==&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2562. Review grading dashboard]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2566. Finish DueDates]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2567. Review rubrics varying by round]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2564. Review calibration]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2568. Finish tabbed view for Assignments, including Topics and Calibration tabs]]&lt;br /&gt;
* [[CSC/ECE 517 Fall 2025 - E2565. Integration of JoinTeamRequests]]&lt;/div&gt;</summary>
		<author><name>Vpatel29</name></author>
	</entry>
</feed>