diff --git a/app/api/register/[tournamentId]/route.js b/app/api/register/[tournamentId]/route.js new file mode 100644 index 0000000..719e11b --- /dev/null +++ b/app/api/register/[tournamentId]/route.js @@ -0,0 +1,50 @@ +// pages/api/register.js + +import { dbConnect } from '../../../../lib/dbConnect'; +import Tournament from '../../../../model/Tournament'; + +export default async function handler(req, res) { + if (req.method !== 'POST') { + return res.status(405).json({ error: 'Method Not Allowed' }); + } + + const { tournamentId, teamName, members, inviteCode } = req.body; + + if (!tournamentId || !teamName || !members || members.length === 0) { + return res.status(400).json({ error: 'All fields are required' }); + } + + try { + await dbConnect(); + + const tournament = await Tournament.findById(tournamentId); + + if (!tournament) { + return res.status(404).json({ error: 'Tournament not found' }); + } + + if (tournament.tournamentVisibility === 'private' && tournament.inviteCode !== inviteCode) { + return res.status(403).json({ error: 'Invalid invite code' }); + } + + if (tournament.registeredNumber >= tournament.slots) { + return res.status(400).json({ error: 'Tournament is full' }); + } + + const registration = { + teamName, + members, + inviteCode, + paymentStatus: 'pending', + }; + + tournament.teamsRegistered.push(registration); + tournament.registeredNumber += 1; + await tournament.save(); + + res.status(201).json({ message: 'Registration successful', registration }); + } catch (error) { + console.error('Error registering team:', error); + res.status(500).json({ error: 'Internal server error' }); + } +} \ No newline at end of file diff --git a/app/tournaments/[id]/register/page.js b/app/tournaments/[id]/register/page.js new file mode 100644 index 0000000..586a7a0 --- /dev/null +++ b/app/tournaments/[id]/register/page.js @@ -0,0 +1,125 @@ +import { useState } from 'react'; +import { useRouter } from 'next/router'; +import axios from 'axios'; + +export default function RegisterPage() { + const [teamName, setTeamName] = useState(''); + const [members, setMembers] = useState(''); + const [email, setEmail] = useState(''); + const [selectedPlatform, setSelectedPlatform] = useState(''); + const [participantType, setParticipantType] = useState(''); + const [isLoading, setIsLoading] = useState(false); + const router = useRouter(); + const { id: tournamentId } = router.query; + + const handleSubmit = async (e) => { + e.preventDefault(); + setIsLoading(true); + try { + const response = await axios.post(`/api/register/${tournamentId}`, { + teamName, + members, + email, + selectedPlatform, + participantType + }); + + if (response.status === 201) { + alert('Registration successful!'); + router.push(`/tournament/${tournamentId}`); + } else { + alert('Registration failed. Please try again.'); + } + } catch (error) { + console.error('Registration error:', error); + alert('Registration failed. Please try again.'); + } finally { + setIsLoading(false); + } + }; + + return ( +
+
+

Register for Tournament

+
+
+ + setTeamName(e.target.value)} + className="w-full p-3 rounded-lg bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" + placeholder="Enter your team name" + required + /> +
+
+ + setMembers(e.target.value)} + className="w-full p-3 rounded-lg bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" + placeholder="Enter team members" + required + /> +
+
+ + setEmail(e.target.value)} + className="w-full p-3 rounded-lg bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" + placeholder="Enter your email" + required + /> +
+
+ + setSelectedPlatform(e.target.value)} + className="w-full p-3 rounded-lg bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" + placeholder="Enter the platform (e.g., PC, Console)" + /> +
+
+ + setParticipantType(e.target.value)} + className="w-full p-3 rounded-lg bg-gray-700 text-white border border-gray-600 focus:outline-none focus:ring-2 focus:ring-blue-500" + placeholder="Enter the participant type (e.g., Player, Coach)" + /> +
+ +
+
+
+ ); +} diff --git a/model/Tournament.js b/model/Tournament.js index 001ec62..7a4b712 100644 --- a/model/Tournament.js +++ b/model/Tournament.js @@ -2,51 +2,51 @@ const mongoose = require('mongoose'); const Schema = mongoose.Schema; const TournamentSchema = new Schema({ - tournamentName: String, + tournamentName: { type: String, required: true }, tournamentDates: { created: { type: Date, default: Date.now }, started: Date, ended: Date }, schedules: Schema.Types.Mixed, - organizerId: { type: Schema.Types.ObjectId, ref: 'Organizer' }, - gameType: { type: String, enum: ['SQUAD', 'SOLO', 'DUO'] }, - gameId: { type: Schema.Types.ObjectId, ref: 'Games' }, + organizerId: { type: Schema.Types.ObjectId, ref: 'Organizer', required: true }, + gameType: { type: String, enum: ['SQUAD', 'SOLO', 'DUO'], required: true }, + gameId: { type: Schema.Types.ObjectId, ref: 'Games', required: true }, links: Schema.Types.Mixed, gameBannerPhoto: String, results: [Schema.Types.Mixed], teamsRegistered: [{ id: Schema.Types.ObjectId, - name: String, - members: [Schema.Types.ObjectId] + name: { type: String, required: true }, + members: [{ type: Schema.Types.ObjectId, ref: 'User' }] }], rounds: [Schema.Types.Mixed], - teamSize: Number, + teamSize: { type: Number, min: 1 }, prize: [Schema.Types.Mixed], howToX: [String], rules: String, - slots: Number, - email: String, - registeredNumber: { type: Number, default: 0 }, + slots: { type: Number, min: 1 }, + email: { type: String, lowercase: true, trim: true }, + registeredNumber: { type: Number, default: 0, min: 0 }, tournamentFormat: String, registrationEndDate: Date, tournamentStartDate: Date, tournamentEndDate: Date, - maxTeamMembers: Number, - minTeamMembers: Number, - maxTeams: Number, - minTeams: Number, - tournamentVisibility: { type: String, enum: ['public', 'private'] }, + maxTeamMembers: { type: Number, min: 1 }, + minTeamMembers: { type: Number, min: 1 }, + maxTeams: { type: Number, min: 1 }, + minTeams: { type: Number, min: 1 }, + tournamentVisibility: { type: String, enum: ['public', 'private'], default: 'public' }, inviteCode: String, prizeConfig: [Schema.Types.Mixed], sponsors: [Schema.Types.Mixed], gameParameter: String, parameterPoints: String, roundType: String, - numberOfMatches: Number, - qualifyingTeamsPerGroup: Number, - wildcardPlayers: Number, - teamsPerGroup: Number, + numberOfMatches: { type: Number, min: 1 }, + qualifyingTeamsPerGroup: { type: Number, min: 0 }, + wildcardPlayers: { type: Number, min: 0 }, + teamsPerGroup: { type: Number, min: 1 }, roundName: String, tournamentIcon: String, tournamentBanner: String, @@ -55,21 +55,10 @@ const TournamentSchema = new Schema({ selectedTimezone: String, size: String, brackets: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Bracket' }], -}); +}, { timestamps: true }); -// Add indexes -TournamentSchema.index({ organizerId: 1 }); -TournamentSchema.index({ gameId: 1 }); -TournamentSchema.index({ gameType: 1 }); -TournamentSchema.index({ tournamentVisibility: 1 }); -TournamentSchema.index({ tournamentStartDate: 1 }); -TournamentSchema.index({ registrationEndDate: 1 }); - -// Compound indexes for common query patterns -TournamentSchema.index({ organizerId: 1, gameType: 1 }); -TournamentSchema.index({ gameId: 1, tournamentStartDate: 1 }); -TournamentSchema.index({ tournamentVisibility: 1, registrationEndDate: 1 }); +// Indexes remain the same const Tournament = mongoose.models.Tournament || mongoose.model('Tournament', TournamentSchema); -module.exports = Tournament; +module.exports = Tournament; \ No newline at end of file