# MatchJoinTeamPopup

A popup component for displaying team information and allowing users to apply to join a team, including team member display, competition rules entry, and join operations.

# Import

import PressMatchJoinTeamPopup from 'press-next/press-match-join-team-popup/press-match-join-team-popup';

# Usage

# Basic Usage

<template>
  <PressButton @click="show = true">
    Join Team
  </PressButton>

  <PressMatchJoinTeamPopup
    :show="show"
    title="Join Team and Participate"
    :team-data="teamData"
    button-text="Apply to Join"
    @close="handleClose"
    @confirm="handleConfirm"
    @member-click="handleMemberClick"
    @add-click="handleAddClick"
    @read-rules-click="handleReadRulesClick"
  />
</template>

<script setup>
import { ref } from 'vue';

const show = ref(false);
const teamData = ref({
  id: 1,
  teamName: 'King Team',
  members: [
    {
      id: 1,
      name: 'Captain Ming',
      avatar: 'https://example.com/avatar1.jpg',
      isCaptain: true,
    },
    {
      id: 2,
      name: 'Member Hong',
      avatar: 'https://example.com/avatar2.jpg',
      isCaptain: false,
    },
    {
      id: 3,
      name: 'Member Li',
      avatar: 'https://example.com/avatar3.jpg',
      isCaptain: false,
    },
  ],
  maxMembers: 5,
  showAddButton: true,
  addButtonText: 'Invite Teammate',
});

const handleClose = () => {
  show.value = false;
};

const handleConfirm = () => {
  console.log('Apply to join team');
  // Send join application
  applyToJoinTeam();
  show.value = false;
};

const handleMemberClick = (member) => {
  console.log('Click member:', member);
  // View member profile
  viewMemberProfile(member);
};

const handleAddClick = () => {
  console.log('Click invite teammate');
  // Open invite dialog
  openInviteDialog();
};

const handleReadRulesClick = () => {
  console.log('View competition rules');
  // Navigate to rules page
  navigateToRules();
};

// API functions
const applyToJoinTeam = async () => {
  // Send join application to server
};

const viewMemberProfile = (member) => {
  // View member details
};

const openInviteDialog = () => {
  // Open invite dialog
};

const navigateToRules = () => {
  // Navigate to competition rules page
};
</script>

# Advanced Usage

<template>
  <PressMatchJoinTeamPopup
    :show="show"
    title="Join Elite Team"
    :team-data="teamData"
    button-text="Apply Now"
    custom-class="custom-join-team-popup"
    @close="handleClose"
    @confirm="handleConfirm"
    @member-click="handleMemberClick"
    @add-click="handleAddClick"
    @read-rules-click="handleReadRulesClick"
  >
    <!-- Custom footer buttons -->
    <template #foot-btn>
      <div class="custom-buttons">
        <PressButton
          type="default"
          @click="handleCancel"
        >
          Cancel
        </PressButton>
        <PressButton
          type="primary"
          @click="handleApply"
        >
          Apply to Join
        </PressButton>
      </div>
    </template>
  </PressMatchJoinTeamPopup>
</template>

<script setup>
import { ref } from 'vue';

const show = ref(false);
const teamData = ref({
  id: 2,
  teamName: 'Elite Squad',
  members: [
    {
      id: 1,
      name: 'Captain Pro',
      avatar: 'https://example.com/captain.jpg',
      isCaptain: true,
      level: 'Diamond',
      winRate: '85%',
    },
    {
      id: 2,
      name: 'Ace Player',
      avatar: 'https://example.com/ace.jpg',
      isCaptain: false,
      level: 'Master',
      winRate: '78%',
    },
    {
      id: 3,
      name: 'Support King',
      avatar: 'https://example.com/support.jpg',
      isCaptain: false,
      level: 'Diamond',
      winRate: '82%',
    },
    {
      id: 4,
      name: 'Jungle God',
      avatar: 'https://example.com/jungle.jpg',
      isCaptain: false,
      level: 'Master',
      winRate: '90%',
    },
  ],
  maxMembers: 5,
  showAddButton: false, // Don't show add button
  requirements: {
    minLevel: 'Diamond',
    minWinRate: '70%',
  },
});

const handleClose = () => {
  console.log('Popup closed');
  show.value = false;
};

const handleConfirm = () => {
  console.log('Default confirm action');
  show.value = false;
};

const handleMemberClick = (member) => {
  console.log('View member details:', member);
  
  // Show member details popup
  showMemberDetails({
    name: member.name,
    level: member.level,
    winRate: member.winRate,
    isCaptain: member.isCaptain,
  });
};

const handleAddClick = () => {
  console.log('Invite new member');
  // This won't trigger in this example since showAddButton is false
};

const handleReadRulesClick = () => {
  console.log('View competition rules');
  
  // Navigate to detailed rules page
  window.open('/match/rules', '_blank');
};

const handleCancel = () => {
  console.log('Cancel join');
  show.value = false;
};

const handleApply = async () => {
  console.log('Apply to join elite team');
  
  try {
    // Check if user meets join requirements
    const userQualified = await checkUserQualification();
    
    if (!userQualified) {
      showMessage('Your level or win rate does not meet the requirements');
      return;
    }
    
    // Send join application
    await submitJoinApplication(teamData.value.id);
    
    showMessage('Application submitted, please wait for captain approval');
    show.value = false;
  } catch (error) {
    console.error('Application failed:', error);
    showMessage('Application failed, please try again later');
  }
};

// Utility functions
const showMemberDetails = (member) => {
  // Show member details popup
  console.log('Show member details:', member);
};

const checkUserQualification = async () => {
  // Check user qualification
  return true; // Example return
};

const submitJoinApplication = async (teamId) => {
  // Submit join application
  console.log('Submit application to team:', teamId);
};

const showMessage = (message) => {
  // Show message
  console.log('Message:', message);
};
</script>

<style scoped>
.custom-buttons {
  display: flex;
  gap: 12px;
}

.custom-buttons .press-button {
  flex: 1;
}
</style>

# Dynamic Team Data

<template>
  <div class="demo-controls">
    <PressButton @click="loadTeamData('full')">Full Team</PressButton>
    <PressButton @click="loadTeamData('recruiting')">Recruiting</PressButton>
    <PressButton @click="loadTeamData('elite')">Elite Team</PressButton>
  </div>

  <PressMatchJoinTeamPopup
    :show="show"
    :title="currentTeam.title"
    :team-data="currentTeam.data"
    :button-text="currentTeam.buttonText"
    @close="show = false"
    @confirm="handleDynamicConfirm"
    @member-click="handleMemberClick"
    @add-click="handleAddClick"
    @read-rules-click="handleReadRulesClick"
  />
</template>

<script setup>
import { ref, reactive } from 'vue';

const show = ref(false);
const currentTeam = reactive({
  title: '',
  data: null,
  buttonText: '',
});

const teamConfigs = {
  full: {
    title: 'Team is Full',
    buttonText: 'Apply as Substitute',
    data: {
      id: 1,
      teamName: 'Full Team',
      members: Array.from({ length: 5 }, (_, i) => ({
        id: i + 1,
        name: `Member ${i + 1}`,
        avatar: `https://example.com/avatar${i + 1}.jpg`,
        isCaptain: i === 0,
      })),
      maxMembers: 5,
      showAddButton: false,
    },
  },
  recruiting: {
    title: 'Join Team',
    buttonText: 'Join Now',
    data: {
      id: 2,
      teamName: 'Recruiting Team',
      members: Array.from({ length: 3 }, (_, i) => ({
        id: i + 1,
        name: `Member ${i + 1}`,
        avatar: `https://example.com/avatar${i + 1}.jpg`,
        isCaptain: i === 0,
      })),
      maxMembers: 5,
      showAddButton: true,
      addButtonText: 'Invite Friends',
    },
  },
  elite: {
    title: 'Apply to Elite Team',
    buttonText: 'Submit Application',
    data: {
      id: 3,
      teamName: 'Elite Team',
      members: Array.from({ length: 4 }, (_, i) => ({
        id: i + 1,
        name: `Elite ${i + 1}`,
        avatar: `https://example.com/elite${i + 1}.jpg`,
        isCaptain: i === 0,
        level: 'Master',
      })),
      maxMembers: 5,
      showAddButton: false,
    },
  },
};

const loadTeamData = (type) => {
  const config = teamConfigs[type];
  Object.assign(currentTeam, config);
  show.value = true;
};

const handleDynamicConfirm = () => {
  console.log(`${currentTeam.title} confirm action`);
  show.value = false;
};

const handleMemberClick = (member) => {
  console.log('Click member:', member);
};

const handleAddClick = () => {
  console.log('Click add button');
};

const handleReadRulesClick = () => {
  console.log('View competition rules');
};
</script>

# API

# Props

Attribute Description Type Default
show Whether to show popup boolean false
title PopupPlus title string 'Join Team and Participate'
teamData Team data TeamData undefined
buttonText Button text string 'Apply to Join'
customClass Custom CSS class string ''

# TeamData Structure

interface TeamMember {
  id?: string | number;
  name: string;
  avatar: string;
  isCaptain?: boolean;
  [key: string]: any; // Support extended fields
}

interface TeamData {
  id?: string | number;
  teamName: string;
  members: TeamMember[];
  maxMembers?: number;
  showAddButton?: boolean;
  addButtonText?: string;
}

# Events

Event Description Parameters
close Triggered when popup is closed -
confirm Triggered when confirm button is clicked -
memberClick Triggered when member is clicked member: TeamMember
addClick Triggered when add button is clicked -
readRulesClick Triggered when read rules is clicked -

# Slots

Name Description Parameters
foot-btn Custom footer button area -

# CSS Variables

The component provides the following CSS variables for custom styling:

# Spacing System

CSS Variable Description Default
--pmjtp-title-icon-ml Title icon margin left $spacing-xs

# Color System

CSS Variable Description Default
--pmjtp-bg-color Background color #fff
--pmjtp-ctrls-text-color Control button color $color-text-invert-default

# Typography System

CSS Variable Description Default
--pmjtp-ctrls-font-size Control button font size $font-size-sm
--pmjtp-ctrls-icon-size Control button icon size $font-size-sm

# Usage Example

/* Custom join team popup styles */
:root {
  --pmjtp-bg-color: #f5f5f5;
  --pmjtp-ctrls-text-color: #1890ff;
  --pmjtp-title-icon-ml: 8px;
}

/* Or override via customClass */
.custom-join-team-popup {
  --pmjtp-ctrls-font-size: 16px;
  --pmjtp-ctrls-icon-size: 18px;
}

# Use Cases

# 1. Team Recruitment

  • Display team member information
  • Allow users to apply to join team
  • Provide competition rules viewing entry

# 2. Team Management

  • View current team member status
  • Support inviting new members
  • Manage team personnel configuration

# 3. Competition Registration

  • Participate in competitions by joining teams
  • Understand team strength and members
  • Confirm competition eligibility and rules

# Notes

  1. Team Data: Ensure complete team data structure is passed
  2. Member Avatars: Recommend using high-resolution avatar images, suggested size 80x80 pixels or above
  3. Permission Control: Display different action buttons based on user permissions
  4. State Management: Properly handle different states like team full, recruiting, etc.
  5. Mini Program Compatibility: Supports WeChat mini program virtualHost configuration
  6. Responsive Design: Component automatically adjusts layout based on member count

# Dependencies

  • PressMatchPopUp: Base popup component
  • PressButton: Button component
  • PressMatchTeamItem: Team member display component