# 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
- Team Data: Ensure complete team data structure is passed
- Member Avatars: Recommend using high-resolution avatar images, suggested size 80x80 pixels or above
- Permission Control: Display different action buttons based on user permissions
- State Management: Properly handle different states like team full, recruiting, etc.
- Mini Program Compatibility: Supports WeChat mini program virtualHost configuration
- Responsive Design: Component automatically adjusts layout based on member count
# Dependencies
PressMatchPopUp: Base popup componentPressButton: Button componentPressMatchTeamItem: Team member display component