diff --git a/src/commands/admin/team/createteam.js b/src/commands/admin/team/createteam.js new file mode 100644 index 0000000..01457c7 --- /dev/null +++ b/src/commands/admin/team/createteam.js @@ -0,0 +1,48 @@ +import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'; +import { TeamService } from '#services/teamService.js'; +import { ConfigService } from '#services/configService.js'; +import logger from '#utils/logger.js'; + +export const data = new SlashCommandBuilder() + .setName('create-team') + .setDescription('Create a team') + .addUserOption((option) => + option.setName('leader').setDescription('The team leader').setRequired(true) + ) + .addStringOption((option) => + option.setName('name').setDescription('The name of the team').setRequired(true) + ) + .addStringOption((option) => + option.setName('description').setDescription('The description of the team').setRequired(false) + ); + +/** + * @param {ChatInputCommandInteraction} interaction + */ +export async function execute(interaction) { + if (!interaction.member.permissions.has('Administrator')) { + const customRole = await ConfigService.getAdminRole(interaction.guildId); + if (customRole) { + const member = await interaction.guild.members.fetch(interaction.user.id); + if (!member.roles.cache.has(customRole)) { + await interaction.reply('You do not have permission to set the approval channel.'); + return; + } + } else { + await interaction.reply('You do not have permission to set the approval channel.'); + return; + } + } + const leader = interaction.options.getUser('leader'); + const name = interaction.options.getString('name'); + const description = interaction.options.getString('description'); + + try { + await TeamService.createTeam(leader.id, name, description); + await interaction.reply(`Team "${name}" (Leader: ${leader.tag}) created successfully!`); + logger.info(`Team "${name}" created successfully by ${interaction.user.tag}`); + } catch (error) { + await interaction.reply(`Error creating team: ${error.message}`); + logger.error(`Error creating team "${name}" by ${interaction.user.tag}: ${error.message}`); + } +} diff --git a/src/commands/admin/team/editteam.js b/src/commands/admin/team/editteam.js new file mode 100644 index 0000000..c956d01 --- /dev/null +++ b/src/commands/admin/team/editteam.js @@ -0,0 +1,73 @@ +import { ChatInputCommandInteraction, SlashCommandBuilder } from 'discord.js'; +import { ConfigService } from '#services/configService.js'; +import { TeamService } from '#services/teamService.js'; +import logger from '#utils/logger.js'; + +export const data = new SlashCommandBuilder() + .setName('edit-team') + .setDescription('Edit a team') + .addStringOption((option) => + option + .setName('team') + .setDescription('Select the team to edit') + .setRequired(true) + .setAutocomplete(true) + ) + .addUserOption((option) => + option.setName('leader').setDescription('The team leader').setRequired(false) + ) + .addStringOption((option) => + option.setName('name').setDescription('The name of the team').setRequired(false) + ) + .addStringOption((option) => + option.setName('description').setDescription('The description of the team').setRequired(false) + ); + +/** + * @param {ChatInputCommandInteraction} interaction + */ +export async function execute(interaction) { + if (!interaction.member.permissions.has('Administrator')) { + const customRole = await ConfigService.getAdminRole(interaction.guildId); + if (customRole) { + const member = await interaction.guild.members.fetch(interaction.user.id); + if (!member.roles.cache.has(customRole)) { + await interaction.reply('You do not have permission to set the approval channel.'); + return; + } + } else { + await interaction.reply('You do not have permission to set the approval channel.'); + return; + } + } + + const teamId = interaction.options.getString('team'); + const leaderId = interaction.options.getUser('leader').id; + const name = interaction.options.getString('name'); + const description = interaction.options.getString('description'); + + if (!name && !description && !leaderId) { + await interaction.reply('Please provide at least one field to edit.'); + return; + } + + try { + const updatedTeam = await TeamService.updateTeam(teamId, leaderId, name, description); + await interaction.reply(`Team ${updatedTeam.name} edited successfully!`); + logger.info(`Team ${updatedTeam.name} ${updatedTeam.id} edited successfully!`); + } catch (error) { + logger.error('Error editing team', error); + await interaction.reply('An error occurred while editing the team.'); + } +} + +/** + * @param {ChatInputCommandInteraction} interaction + */ +export async function autocomplete(interaction) { + const focusedValue = interaction.options.getFocused(); + const events = await TeamService.getTeams(); + const filtered = events.filter((event) => event.name.startsWith(focusedValue)); + const choices = filtered.map((event) => event).slice(0, 25); + await interaction.respond(choices.map((choice) => ({ name: choice.name, value: choice.id }))); +} diff --git a/src/services/teamService.js b/src/services/teamService.js new file mode 100644 index 0000000..0a36f8b --- /dev/null +++ b/src/services/teamService.js @@ -0,0 +1,124 @@ +import prisma from '#utils/prisma.js'; +import logger from '#utils/logger.js'; + +export class TeamService { + /** + * Create a new team in the database + * @param {String} leaderId - (Optional) The ID of the team leader + * @param {String} name - The name of the team + * @param {String} description - The description of the team + * @returns {Promise} + */ + static async createTeam(leaderId, name, description) { + // Validate inputs + if (!name || !leaderId) { + throw new Error('Team name and leader id is required'); + } + // Create the team + try { + await prisma.team.create({ + data: { + name, + description, + leader: { + connect: { + discordId: leaderId, + }, + }, + }, + }); + } catch (error) { + logger.error('Error creating team', error.message); + throw error; + } + } + + /** + * Get all teams + * @returns {Promise} An array of teams + */ + static async getTeams() { + try { + const teams = await prisma.team.findMany({ + orderBy: { + name: 'asc', + }, + }); + return teams; + } catch (error) { + logger.error('Error getting teams', error); + throw error; + } + } + + /** + * Delete a team by ID + * @param {String} teamId - The ID of the team + * @returns {Promise} + */ + static async deleteTeam(teamId) { + try { + await prisma.team.delete({ + where: { + id: teamId, + }, + }); + } catch (error) { + logger.error('Error deleting team', error); + throw error; + } + } + + /** + * Get a team by ID + * @param {String} teamId - The ID of the team + * @returns {Promise} The team object + */ + static async getTeamById(teamId) { + try { + const team = await prisma.team.findUnique({ + where: { + id: teamId, + }, + }); + if (!team) { + throw new Error('Team not found'); + } + return team; + } catch (error) { + logger.error('Error getting team by ID', error); + throw error; + } + } + /** + * Update a team by ID + * @param {String} teamId - The ID of the team + * @param {String} leaderId - The ID of the team leader + * @param {Object} data - The data to update + * @returns {Promise} The updated team object + */ + static async updateTeam(teamId, leaderId, name, description) { + const updateData = {}; + try { + if (leaderId) { + updateData.leader = { + connect: { + discordId: leaderId, + }, + }; + } + if (name) updateData.name = name; + if (description) updateData.description = description; + + return await prisma.team.update({ + where: { + id: teamId, + }, + data: updateData, + }); + } catch (error) { + logger.error('Error updating team', error); + throw error; + } + } +}