Translate App into German
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
name,tag,description
|
name,tag,description
|
||||||
Team Alpha,ALP,A competitive esports team
|
Team Alpha,ALP,Ein wettbewerbsorientiertes E-Sport-Team
|
||||||
Team Beta,BET,New challengers on the scene
|
Team Beta,BET,Neue Herausforderer in der Szene
|
||||||
Team Gamma,GAM,Veteran tournament winners
|
Team Gamma,GAM,Erfahrene Turniersieger
|
||||||
Team Delta,DEL,Rising stars in the community
|
Team Delta,DEL,Aufstrebende Stars der Community
|
||||||
Team Epsilon,EPS,Strategic gameplay specialists
|
Team Epsilon,EPS,Spezialisten für strategisches Gameplay
|
||||||
Team Zeta,ZET,Fast-paced aggressive players
|
Team Zeta,ZET,Schnelle und aggressive Spieler
|
||||||
|
|||||||
|
@@ -1,4 +1,4 @@
|
|||||||
name,description,maxTeamAmount,currentTeamAmount,registrationStartDate,registrationEndDate
|
name,description,maxTeamAmount,currentTeamAmount,registrationStartDate,registrationEndDate
|
||||||
Demo Tournament ,This is a demo tournament, 2, 0, 2026-02-01, 2026-02-28
|
Demo-Turnier,Dies ist ein Demo-Turnier, 2, 0, 2026-02-01, 2026-02-28
|
||||||
Demo Tournament 2,This is a second demo tournament, 4, 5, 2026-03-01, 2026-03-15
|
Demo-Turnier 2,Dies ist ein zweites Demo-Turnier, 4, 5, 2026-03-01, 2026-03-15
|
||||||
Demo Tournament 3,This is a third demo tournament, 8, 8, 2026-03-15, 2026-03-20
|
Demo-Turnier 3,Dies ist ein drittes Demo-Turnier, 8, 8, 2026-03-15, 2026-03-20
|
||||||
|
|||||||
|
@@ -37,7 +37,7 @@ app.get('/tournaments', async (req: Request, res: Response) => {
|
|||||||
app.get('/tournaments/:id', async (req: Request, res: Response) => {
|
app.get('/tournaments/:id', async (req: Request, res: Response) => {
|
||||||
const tournament = await tournamentService.getTournamentById(+req.params.id);
|
const tournament = await tournamentService.getTournamentById(+req.params.id);
|
||||||
if (!tournament) {
|
if (!tournament) {
|
||||||
return res.status(404).send({error: 'Tournament not found'});
|
return res.status(404).send({error: 'Turnier nicht gefunden'});
|
||||||
}
|
}
|
||||||
res.send(tournament);
|
res.send(tournament);
|
||||||
});
|
});
|
||||||
@@ -48,7 +48,7 @@ app.post('/tournaments', authMiddleware, async (req: Request, res: Response) =>
|
|||||||
res.status(201).send();
|
res.status(201).send();
|
||||||
} catch (err){
|
} catch (err){
|
||||||
console.log(err);
|
console.log(err);
|
||||||
res.status(400).send({error: 'Failed to create tournament'});
|
res.status(400).send({error: 'Turnier konnte nicht erstellt werden'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -56,18 +56,18 @@ app.put('/tournaments/:id', authMiddleware, async (req: Request, res: Response)
|
|||||||
try {
|
try {
|
||||||
await tournamentService.updateTournament(+req.params.id, req.body);
|
await tournamentService.updateTournament(+req.params.id, req.body);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return res.status(400).send({error: 'Failed to update Tournament'});
|
return res.status(400).send({error: 'Turnier konnte nicht aktualisiert werden'});
|
||||||
}
|
}
|
||||||
res.status(200).send({message: 'Tournament updated successfully'});
|
res.status(200).send({message: 'Turnier erfolgreich aktualisiert'});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.delete('/tournaments/:id', authMiddleware, async (req: Request, res: Response) => {
|
app.delete('/tournaments/:id', authMiddleware, async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
await tournamentService.deleteTournament(+req.params.id);
|
await tournamentService.deleteTournament(+req.params.id);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return res.status(400).send({error: 'Failed to delete Tournament'});
|
return res.status(400).send({error: 'Turnier konnte nicht gelöscht werden'});
|
||||||
}
|
}
|
||||||
res.status(200).send({message: 'Tournament deleted successfully'});
|
res.status(200).send({message: 'Turnier erfolgreich gelöscht'});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/tournaments/:id/bracket', authMiddleware, async (req: Request, res: Response) => {
|
app.post('/tournaments/:id/bracket', authMiddleware, async (req: Request, res: Response) => {
|
||||||
@@ -77,14 +77,14 @@ app.post('/tournaments/:id/bracket', authMiddleware, async (req: Request, res: R
|
|||||||
const teamIds = teams.map(team => team.id);
|
const teamIds = teams.map(team => team.id);
|
||||||
|
|
||||||
if (teamIds.length < 2) {
|
if (teamIds.length < 2) {
|
||||||
return res.status(400).send({error: 'At least 2 teams are required to initialize bracket'});
|
return res.status(400).send({error: 'Mindestens 2 Teams sind erforderlich, um den Turnierbaum zu initialisieren'});
|
||||||
}
|
}
|
||||||
|
|
||||||
await matchService.initializeBracket(tournamentId, teamIds);
|
await matchService.initializeBracket(tournamentId, teamIds);
|
||||||
res.status(201).send({message: 'Bracket initialized successfully'});
|
res.status(201).send({message: 'Turnierbaum erfolgreich initialisiert'});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
res.status(400).send({error: 'Failed to initialize bracket'});
|
res.status(400).send({error: 'Turnierbaum konnte nicht initialisiert werden'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ app.get('/tournaments/:id/matches', async (req: Request, res: Response) => {
|
|||||||
res.send(matches);
|
res.send(matches);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
res.status(400).send({error: 'Failed to get matches'});
|
res.status(400).send({error: 'Matches konnten nicht geladen werden'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -102,23 +102,23 @@ app.put('/matches/:id/winner', authMiddleware, async (req: Request, res: Respons
|
|||||||
try {
|
try {
|
||||||
const {winnerId} = req.body;
|
const {winnerId} = req.body;
|
||||||
if (!winnerId) {
|
if (!winnerId) {
|
||||||
return res.status(400).send({error: 'winnerId is required'});
|
return res.status(400).send({error: 'winnerId ist erforderlich'});
|
||||||
}
|
}
|
||||||
await matchService.setMatchWinner(+req.params.id, +winnerId);
|
await matchService.setMatchWinner(+req.params.id, +winnerId);
|
||||||
res.status(200).send({message: 'Winner set successfully'});
|
res.status(200).send({message: 'Sieger erfolgreich festgelegt'});
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
res.status(400).send({error: err.message || 'Failed to set winner'});
|
res.status(400).send({error: err.message || 'Sieger konnte nicht festgelegt werden'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.delete('/matches/:id/winner', authMiddleware, async (req: Request, res: Response) => {
|
app.delete('/matches/:id/winner', authMiddleware, async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
await matchService.resetMatch(+req.params.id);
|
await matchService.resetMatch(+req.params.id);
|
||||||
res.status(200).send({message: 'Match reset successfully'});
|
res.status(200).send({message: 'Match erfolgreich zurückgesetzt'});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
res.status(400).send({error: 'Failed to reset match'});
|
res.status(400).send({error: 'Match konnte nicht zurückgesetzt werden'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -130,7 +130,7 @@ app.get('/teams', async (req: Request, res: Response) => {
|
|||||||
app.get('/teams/:id', async (req: Request, res: Response) => {
|
app.get('/teams/:id', async (req: Request, res: Response) => {
|
||||||
const team = await teamService.getTeamById(+req.params.id);
|
const team = await teamService.getTeamById(+req.params.id);
|
||||||
if (!team) {
|
if (!team) {
|
||||||
return res.status(404).send({error: 'Team not found'});
|
return res.status(404).send({error: 'Team nicht gefunden'});
|
||||||
}
|
}
|
||||||
res.send(team);
|
res.send(team);
|
||||||
});
|
});
|
||||||
@@ -138,10 +138,10 @@ app.get('/teams/:id', async (req: Request, res: Response) => {
|
|||||||
app.post('/teams', authMiddleware, async (req: Request, res: Response) => {
|
app.post('/teams', authMiddleware, async (req: Request, res: Response) => {
|
||||||
const {name, tag, description} = req.body;
|
const {name, tag, description} = req.body;
|
||||||
if (!name || !tag) {
|
if (!name || !tag) {
|
||||||
return res.status(400).send({error: 'name and tag are required'});
|
return res.status(400).send({error: 'Name und Kürzel sind erforderlich'});
|
||||||
}
|
}
|
||||||
if (tag.length > 3) {
|
if (tag.length > 3) {
|
||||||
return res.status(400).send({error: 'tag must be at most 3 characters'});
|
return res.status(400).send({error: 'Das Kürzel darf höchstens 3 Zeichen lang sein'});
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const team = await teamService.addTeam({name, tag, description: description ?? ''});
|
const team = await teamService.addTeam({name, tag, description: description ?? ''});
|
||||||
@@ -151,30 +151,30 @@ app.post('/teams', authMiddleware, async (req: Request, res: Response) => {
|
|||||||
res.status(201).send(team);
|
res.status(201).send(team);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
res.status(400).send({error: 'Failed to create team'});
|
res.status(400).send({error: 'Team konnte nicht erstellt werden'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.put('/teams/:id', authMiddleware, async (req: Request, res: Response) => {
|
app.put('/teams/:id', authMiddleware, async (req: Request, res: Response) => {
|
||||||
const {tag} = req.body;
|
const {tag} = req.body;
|
||||||
if (tag && tag.length > 3) {
|
if (tag && tag.length > 3) {
|
||||||
return res.status(400).send({error: 'tag must be at most 3 characters'});
|
return res.status(400).send({error: 'Das Kürzel darf höchstens 3 Zeichen lang sein'});
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await teamService.updateTeam(+req.params.id, req.body);
|
await teamService.updateTeam(+req.params.id, req.body);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return res.status(400).send({error: 'Failed to update team'});
|
return res.status(400).send({error: 'Team konnte nicht aktualisiert werden'});
|
||||||
}
|
}
|
||||||
res.status(200).send({message: 'Team updated successfully'});
|
res.status(200).send({message: 'Team erfolgreich aktualisiert'});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.delete('/teams/:id', authMiddleware, async (req: Request, res: Response) => {
|
app.delete('/teams/:id', authMiddleware, async (req: Request, res: Response) => {
|
||||||
try {
|
try {
|
||||||
await teamService.deleteTeam(+req.params.id);
|
await teamService.deleteTeam(+req.params.id);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return res.status(400).send({error: 'Failed to delete team'});
|
return res.status(400).send({error: 'Team konnte nicht gelöscht werden'});
|
||||||
}
|
}
|
||||||
res.status(200).send({message: 'Team deleted successfully'});
|
res.status(200).send({message: 'Team erfolgreich gelöscht'});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/tournaments/:id/teams', async (req: Request, res: Response) => {
|
app.get('/tournaments/:id/teams', async (req: Request, res: Response) => {
|
||||||
@@ -185,16 +185,16 @@ app.get('/tournaments/:id/teams', async (req: Request, res: Response) => {
|
|||||||
app.post('/tournaments/:id/teams', authMiddleware, async (req: Request, res: Response) => {
|
app.post('/tournaments/:id/teams', authMiddleware, async (req: Request, res: Response) => {
|
||||||
const {teamId} = req.body;
|
const {teamId} = req.body;
|
||||||
if (!teamId) {
|
if (!teamId) {
|
||||||
return res.status(400).send({error: 'teamId is required'});
|
return res.status(400).send({error: 'teamId ist erforderlich'});
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const entry = await teamService.registerTeamForTournament(+req.params.id, +teamId);
|
const entry = await teamService.registerTeamForTournament(+req.params.id, +teamId);
|
||||||
res.status(201).send(entry);
|
res.status(201).send(entry);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err.message?.includes('UNIQUE constraint failed')) {
|
if (err.message?.includes('UNIQUE constraint failed')) {
|
||||||
return res.status(409).send({error: 'Team is already registered for this tournament'});
|
return res.status(409).send({error: 'Das Team ist bereits für dieses Turnier angemeldet'});
|
||||||
}
|
}
|
||||||
res.status(400).send({error: 'Failed to register team'});
|
res.status(400).send({error: 'Team konnte nicht für das Turnier angemeldet werden'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -202,9 +202,9 @@ app.delete('/tournaments/:id/teams/:teamId', authMiddleware, async (req: Request
|
|||||||
try {
|
try {
|
||||||
await teamService.removeTeamFromTournament(+req.params.id, +req.params.teamId);
|
await teamService.removeTeamFromTournament(+req.params.id, +req.params.teamId);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return res.status(400).send({error: 'Failed to remove team from tournament'});
|
return res.status(400).send({error: 'Team konnte nicht aus dem Turnier entfernt werden'});
|
||||||
}
|
}
|
||||||
res.status(200).send({message: 'Team removed from tournament'});
|
res.status(200).send({message: 'Team aus dem Turnier entfernt'});
|
||||||
});
|
});
|
||||||
|
|
||||||
app.get('/teams/:id/tournaments', async (req: Request, res: Response) => {
|
app.get('/teams/:id/tournaments', async (req: Request, res: Response) => {
|
||||||
@@ -220,7 +220,7 @@ app.get('/users/me/teams', authMiddleware, async (req: Request, res: Response) =
|
|||||||
res.send(teams);
|
res.send(teams);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
res.status(400).send({error: 'Failed to get user teams'});
|
res.status(400).send({error: 'Eigene Teams konnten nicht geladen werden'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -232,14 +232,14 @@ app.post('/teams/:id/members', authMiddleware, async (req: Request, res: Respons
|
|||||||
|
|
||||||
const isInTeam = await teamService.isUserInTeam(teamId, userId);
|
const isInTeam = await teamService.isUserInTeam(teamId, userId);
|
||||||
if (isInTeam) {
|
if (isInTeam) {
|
||||||
return res.status(409).send({error: 'User is already a member of this team'});
|
return res.status(409).send({error: 'Du bist bereits Mitglied dieses Teams'});
|
||||||
}
|
}
|
||||||
|
|
||||||
const member = await teamService.addTeamMember(teamId, userId, 'member');
|
const member = await teamService.addTeamMember(teamId, userId, 'member');
|
||||||
res.status(201).send(member);
|
res.status(201).send(member);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
res.status(400).send({error: 'Failed to join team'});
|
res.status(400).send({error: 'Beitritt zum Team fehlgeschlagen'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -249,10 +249,10 @@ app.delete('/teams/:id/members/me', authMiddleware, async (req: Request, res: Re
|
|||||||
const userId = req.user.id;
|
const userId = req.user.id;
|
||||||
const teamId = +req.params.id;
|
const teamId = +req.params.id;
|
||||||
await teamService.removeTeamMember(teamId, userId);
|
await teamService.removeTeamMember(teamId, userId);
|
||||||
res.status(200).send({message: 'Left team successfully'});
|
res.status(200).send({message: 'Team erfolgreich verlassen'});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
res.status(400).send({error: 'Failed to leave team'});
|
res.status(400).send({error: 'Team konnte nicht verlassen werden'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -262,36 +262,36 @@ app.get('/teams/:id/members', async (req: Request, res: Response) => {
|
|||||||
res.send(members);
|
res.send(members);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.log(err);
|
console.log(err);
|
||||||
res.status(400).send({error: 'Failed to get team members'});
|
res.status(400).send({error: 'Teammitglieder konnten nicht geladen werden'});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/register', async (req: Request, res: Response) => {
|
app.post('/register', async (req: Request, res: Response) => {
|
||||||
const { username, password } = req.body;
|
const { username, password } = req.body;
|
||||||
if (!username || !password) {
|
if (!username || !password) {
|
||||||
return res.status(400).send({ error: 'Username and password are required' });
|
return res.status(400).send({ error: 'Benutzername und Passwort sind erforderlich' });
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const user = await userService.register(username, password);
|
const user = await userService.register(username, password);
|
||||||
res.status(201).send(user);
|
res.status(201).send(user);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
if (err.message?.includes('UNIQUE constraint failed')) {
|
if (err.message?.includes('UNIQUE constraint failed')) {
|
||||||
return res.status(409).send({ error: 'Username already exists' });
|
return res.status(409).send({ error: 'Benutzername existiert bereits' });
|
||||||
}
|
}
|
||||||
res.status(500).send({ error: 'Registration failed' });
|
res.status(500).send({ error: 'Registrierung fehlgeschlagen' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post('/login', async (req: Request, res: Response) => {
|
app.post('/login', async (req: Request, res: Response) => {
|
||||||
const { username, password } = req.body;
|
const { username, password } = req.body;
|
||||||
if (!username || !password) {
|
if (!username || !password) {
|
||||||
return res.status(400).send({ error: 'Username and password are required' });
|
return res.status(400).send({ error: 'Benutzername und Passwort sind erforderlich' });
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const user = await userService.login(username, password);
|
const user = await userService.login(username, password);
|
||||||
res.status(200).send(user);
|
res.status(200).send(user);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
res.status(401).send({ error: err.message || 'Login failed' });
|
res.status(401).send({ error: err.message || 'Anmeldung fehlgeschlagen' });
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ const JWT_SECRET = process.env.JWT_SECRET || "key"
|
|||||||
export const authMiddleware = (req: Request, res: Response, next: NextFunction) => {
|
export const authMiddleware = (req: Request, res: Response, next: NextFunction) => {
|
||||||
const authHeader = req.headers.authorization;
|
const authHeader = req.headers.authorization;
|
||||||
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
if (!authHeader || !authHeader.startsWith('Bearer ')) {
|
||||||
return res.status(401).send({ error: 'Unauthorized: No token provided' });
|
return res.status(401).send({ error: 'Nicht autorisiert: Kein Token angegeben' });
|
||||||
}
|
}
|
||||||
const token = authHeader.split(' ')[1];
|
const token = authHeader.split(' ')[1];
|
||||||
try {
|
try {
|
||||||
@@ -17,6 +17,6 @@ export const authMiddleware = (req: Request, res: Response, next: NextFunction)
|
|||||||
|
|
||||||
next();
|
next();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
return res.status(401).send({ error: 'Unauthorized: Invalid token' });
|
return res.status(401).send({ error: 'Nicht autorisiert: Ungültiger Token' });
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -120,11 +120,11 @@ export class MatchService {
|
|||||||
[matchId],
|
[matchId],
|
||||||
(err, match: any) => {
|
(err, match: any) => {
|
||||||
if (err) return reject(err);
|
if (err) return reject(err);
|
||||||
if (!match) return reject(new Error('Match not found'));
|
if (!match) return reject(new Error('Match nicht gefunden'));
|
||||||
|
|
||||||
// Validate that the winnerId is one of the participants
|
// Validate that the winnerId is one of the participants
|
||||||
if (match.team1Id !== winnerId && match.team2Id !== winnerId) {
|
if (match.team1Id !== winnerId && match.team2Id !== winnerId) {
|
||||||
return reject(new Error('Winner must be one of the match participants'));
|
return reject(new Error('Der Sieger muss eines der Teams dieses Matches sein'));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the match with winner
|
// Update the match with winner
|
||||||
@@ -182,7 +182,7 @@ export class MatchService {
|
|||||||
[matchId],
|
[matchId],
|
||||||
(err, match: any) => {
|
(err, match: any) => {
|
||||||
if (err) return reject(err);
|
if (err) return reject(err);
|
||||||
if (!match) return reject(new Error('Match not found'));
|
if (!match) return reject(new Error('Match nicht gefunden'));
|
||||||
|
|
||||||
const previousWinnerId = match.winnerId;
|
const previousWinnerId = match.winnerId;
|
||||||
|
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ export class TeamService {
|
|||||||
(err: Error | null, row: any) => {
|
(err: Error | null, row: any) => {
|
||||||
if (err) return reject(err);
|
if (err) return reject(err);
|
||||||
if (row.count >= 4) {
|
if (row.count >= 4) {
|
||||||
return reject(new Error('Team already has maximum of 4 members'));
|
return reject(new Error('Das Team hat bereits die maximale Anzahl von 4 Mitgliedern'));
|
||||||
}
|
}
|
||||||
|
|
||||||
const stmt = this.db.prepare(`INSERT INTO TeamMembers (teamId, userId, role) VALUES (?, ?, ?)`);
|
const stmt = this.db.prepare(`INSERT INTO TeamMembers (teamId, userId, role) VALUES (?, ?, ?)`);
|
||||||
|
|||||||
@@ -74,12 +74,12 @@ export class UserService {
|
|||||||
return reject(err);
|
return reject(err);
|
||||||
}
|
}
|
||||||
if (!user) {
|
if (!user) {
|
||||||
return reject(new Error('User not found'));
|
return reject(new Error('Benutzer nicht gefunden'));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const valid = await argon2.verify(user.password, password);
|
const valid = await argon2.verify(user.password, password);
|
||||||
if (!valid) {
|
if (!valid) {
|
||||||
return reject(new Error('Invalid password'));
|
return reject(new Error('Ungültiges Passwort'));
|
||||||
}
|
}
|
||||||
const token = jwt.sign({ id: user.id, username: user.username }, JWT_SECRET, { expiresIn: '7d' });
|
const token = jwt.sign({ id: user.id, username: user.username }, JWT_SECRET, { expiresIn: '7d' });
|
||||||
resolve({ id: user.id, username: user.username, token });
|
resolve({ id: user.id, username: user.username, token });
|
||||||
|
|||||||
@@ -110,3 +110,41 @@ Folgende Dateien wurden in diesem Prompt verändert:
|
|||||||
- frontend_splatournament_manager/lib/providers/match_provider.dart (neu erstellt)
|
- frontend_splatournament_manager/lib/providers/match_provider.dart (neu erstellt)
|
||||||
- frontend_splatournament_manager/lib/main.dart
|
- frontend_splatournament_manager/lib/main.dart
|
||||||
- frontend_splatournament_manager/lib/pages/tournament_bracket_page.dart
|
- frontend_splatournament_manager/lib/pages/tournament_bracket_page.dart
|
||||||
|
|
||||||
|
## 13.03.2026
|
||||||
|
|
||||||
|
- Translate the entire app into German, and also translate the relevant DB seeding CSVs.
|
||||||
|
Folgende Dateien wurden in diesem Prompt verändert:
|
||||||
|
- backend_splatournament_manager/src/app.ts
|
||||||
|
- backend_splatournament_manager/src/middlewares/auth-middleware.ts
|
||||||
|
- backend_splatournament_manager/src/services/user-service.ts
|
||||||
|
- backend_splatournament_manager/src/services/team-service.ts
|
||||||
|
- backend_splatournament_manager/src/services/match-service.ts
|
||||||
|
- backend_splatournament_manager/dist/csv/teams.csv
|
||||||
|
- backend_splatournament_manager/dist/csv/tournaments.csv
|
||||||
|
- frontend_splatournament_manager/pubspec.yaml
|
||||||
|
- frontend_splatournament_manager/lib/main.dart
|
||||||
|
- frontend_splatournament_manager/lib/pages/login_page.dart
|
||||||
|
- frontend_splatournament_manager/lib/pages/home_page.dart
|
||||||
|
- frontend_splatournament_manager/lib/pages/create_team_page.dart
|
||||||
|
- frontend_splatournament_manager/lib/pages/create_tournament_page.dart
|
||||||
|
- frontend_splatournament_manager/lib/pages/settings_page.dart
|
||||||
|
- frontend_splatournament_manager/lib/pages/tournament_detail_page.dart
|
||||||
|
- frontend_splatournament_manager/lib/pages/tournament_bracket_page.dart
|
||||||
|
- frontend_splatournament_manager/lib/providers/tournament_provider.dart
|
||||||
|
- frontend_splatournament_manager/lib/providers/match_provider.dart
|
||||||
|
- frontend_splatournament_manager/lib/services/auth_service.dart
|
||||||
|
- frontend_splatournament_manager/lib/services/team_service.dart
|
||||||
|
- frontend_splatournament_manager/lib/widgets/available_tournament_list.dart
|
||||||
|
- frontend_splatournament_manager/lib/widgets/profile_widget.dart
|
||||||
|
- frontend_splatournament_manager/lib/widgets/teams_list_widget.dart
|
||||||
|
- frontend_splatournament_manager/lib/widgets/theme_selector_widget.dart
|
||||||
|
- frontend_splatournament_manager/lib/widgets/my_teams_widget.dart
|
||||||
|
- frontend_splatournament_manager/lib/widgets/my_tournaments_carousel.dart
|
||||||
|
- frontend_splatournament_manager/web/index.html
|
||||||
|
- frontend_splatournament_manager/web/manifest.json
|
||||||
|
- frontend_splatournament_manager/android/app/src/main/AndroidManifest.xml
|
||||||
|
- frontend_splatournament_manager/ios/Runner/Info.plist
|
||||||
|
- frontend_splatournament_manager/linux/runner/my_application.cc
|
||||||
|
- frontend_splatournament_manager/windows/runner/main.cpp
|
||||||
|
- frontend_splatournament_manager/windows/runner/Runner.rc
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
<uses-permission android:name="android.permission.INTERNET"/>
|
||||||
<application
|
<application
|
||||||
android:label="frontend_splatournament_manager"
|
android:label="Splatournament Manager"
|
||||||
android:name="${applicationName}"
|
android:name="${applicationName}"
|
||||||
android:icon="@mipmap/ic_launcher">
|
android:icon="@mipmap/ic_launcher">
|
||||||
<activity
|
<activity
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>Frontend Splatournament Manager</string>
|
<string>Splatournament Manager</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleIdentifier</key>
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>6.0</string>
|
<string>6.0</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleName</key>
|
||||||
<string>frontend_splatournament_manager</string>
|
<string>Splatournament Manager</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:frontend_splatournament_manager/pages/home_page.dart';
|
import 'package:frontend_splatournament_manager/pages/home_page.dart';
|
||||||
import 'package:frontend_splatournament_manager/pages/login_page.dart';
|
import 'package:frontend_splatournament_manager/pages/login_page.dart';
|
||||||
import 'package:frontend_splatournament_manager/pages/settings_page.dart';
|
import 'package:frontend_splatournament_manager/pages/settings_page.dart';
|
||||||
@@ -34,6 +35,13 @@ class SplatournamentApp extends StatelessWidget {
|
|||||||
return MaterialApp.router(
|
return MaterialApp.router(
|
||||||
title: 'Splatournament Manager',
|
title: 'Splatournament Manager',
|
||||||
routerConfig: routes,
|
routerConfig: routes,
|
||||||
|
locale: const Locale('de', 'DE'),
|
||||||
|
supportedLocales: const [Locale('de', 'DE')],
|
||||||
|
localizationsDelegates: const [
|
||||||
|
GlobalMaterialLocalizations.delegate,
|
||||||
|
GlobalWidgetsLocalizations.delegate,
|
||||||
|
GlobalCupertinoLocalizations.delegate,
|
||||||
|
],
|
||||||
themeMode: themeProvider.themeMode,
|
themeMode: themeProvider.themeMode,
|
||||||
theme: themeProvider.lightTheme,
|
theme: themeProvider.lightTheme,
|
||||||
darkTheme: themeProvider.darkTheme,
|
darkTheme: themeProvider.darkTheme,
|
||||||
|
|||||||
@@ -23,9 +23,13 @@ class _CreateTeamPageState extends State<CreateTeamPage> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
_nameController = TextEditingController(text: widget.teamToEdit?.name ?? '');
|
_nameController = TextEditingController(
|
||||||
|
text: widget.teamToEdit?.name ?? '',
|
||||||
|
);
|
||||||
_tagController = TextEditingController(text: widget.teamToEdit?.tag ?? '');
|
_tagController = TextEditingController(text: widget.teamToEdit?.tag ?? '');
|
||||||
_descriptionController = TextEditingController(text: widget.teamToEdit?.description ?? '');
|
_descriptionController = TextEditingController(
|
||||||
|
text: widget.teamToEdit?.description ?? '',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _submitForm() async {
|
void _submitForm() async {
|
||||||
@@ -42,9 +46,9 @@ class _CreateTeamPageState extends State<CreateTeamPage> {
|
|||||||
tag: _tagController.text,
|
tag: _tagController.text,
|
||||||
description: _descriptionController.text,
|
description: _descriptionController.text,
|
||||||
);
|
);
|
||||||
if (!context.mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text('Team updated successfully')),
|
const SnackBar(content: Text('Team erfolgreich aktualisiert')),
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
await provider.createTeam(
|
await provider.createTeam(
|
||||||
@@ -52,20 +56,24 @@ class _CreateTeamPageState extends State<CreateTeamPage> {
|
|||||||
tag: _tagController.text,
|
tag: _tagController.text,
|
||||||
description: _descriptionController.text,
|
description: _descriptionController.text,
|
||||||
);
|
);
|
||||||
if (!context.mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text('Team created successfully')),
|
const SnackBar(content: Text('Team erfolgreich erstellt')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (!context.mounted) return;
|
if (!mounted) return;
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!context.mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('Error: $e')),
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
'Fehler: ${e.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
} finally {
|
} finally {
|
||||||
if (context.mounted) setState(() => _isLoading = false);
|
if (mounted) setState(() => _isLoading = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +90,7 @@ class _CreateTeamPageState extends State<CreateTeamPage> {
|
|||||||
final isEditing = widget.teamToEdit != null;
|
final isEditing = widget.teamToEdit != null;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(isEditing ? 'Edit Team' : 'Create Team'),
|
title: Text(isEditing ? 'Team bearbeiten' : 'Team erstellen'),
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
@@ -94,12 +102,12 @@ class _CreateTeamPageState extends State<CreateTeamPage> {
|
|||||||
TextFormField(
|
TextFormField(
|
||||||
controller: _nameController,
|
controller: _nameController,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Team Name',
|
labelText: 'Teamname',
|
||||||
hintText: 'Enter team name',
|
hintText: 'Teamname eingeben',
|
||||||
),
|
),
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Team name is required';
|
return 'Der Teamname ist erforderlich';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
@@ -108,17 +116,17 @@ class _CreateTeamPageState extends State<CreateTeamPage> {
|
|||||||
TextFormField(
|
TextFormField(
|
||||||
controller: _tagController,
|
controller: _tagController,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Team Tag',
|
labelText: 'Teamkürzel',
|
||||||
hintText: 'Enter team tag (max 3 characters)',
|
hintText: 'Teamkürzel eingeben (max. 3 Zeichen)',
|
||||||
),
|
),
|
||||||
maxLength: 3,
|
maxLength: 3,
|
||||||
textCapitalization: TextCapitalization.characters,
|
textCapitalization: TextCapitalization.characters,
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.isEmpty) {
|
if (value == null || value.isEmpty) {
|
||||||
return 'Team tag is required';
|
return 'Das Teamkürzel ist erforderlich';
|
||||||
}
|
}
|
||||||
if (value.length > 3) {
|
if (value.length > 3) {
|
||||||
return 'Tag must be at most 3 characters';
|
return 'Das Kürzel darf höchstens 3 Zeichen lang sein';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
@@ -127,8 +135,8 @@ class _CreateTeamPageState extends State<CreateTeamPage> {
|
|||||||
TextFormField(
|
TextFormField(
|
||||||
controller: _descriptionController,
|
controller: _descriptionController,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Description',
|
labelText: 'Beschreibung',
|
||||||
hintText: 'Enter team description (optional)',
|
hintText: 'Teambeschreibung eingeben (optional)',
|
||||||
),
|
),
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
),
|
),
|
||||||
@@ -137,7 +145,7 @@ class _CreateTeamPageState extends State<CreateTeamPage> {
|
|||||||
onPressed: _isLoading ? null : _submitForm,
|
onPressed: _isLoading ? null : _submitForm,
|
||||||
child: _isLoading
|
child: _isLoading
|
||||||
? const CircularProgressIndicator()
|
? const CircularProgressIndicator()
|
||||||
: Text(isEditing ? 'Update Team' : 'Create Team'),
|
: Text(isEditing ? 'Team aktualisieren' : 'Team erstellen'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -22,12 +22,13 @@ class _CreateTournamentPageState extends State<CreateTournamentPage> {
|
|||||||
|
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
|
|
||||||
final DateFormat _dateFormat = DateFormat('yyyy-MM-dd');
|
final DateFormat _dateFormat = DateFormat('dd.MM.yyyy', 'de_DE');
|
||||||
|
|
||||||
Future<void> _selectDate(BuildContext context, bool isStart) async {
|
Future<void> _selectDate(BuildContext context, bool isStart) async {
|
||||||
final initialDate = DateTime.now();
|
final initialDate = DateTime.now();
|
||||||
final picked = await showDatePicker(
|
final picked = await showDatePicker(
|
||||||
context: context,
|
context: context,
|
||||||
|
locale: const Locale('de', 'DE'),
|
||||||
initialDate: initialDate,
|
initialDate: initialDate,
|
||||||
firstDate: initialDate,
|
firstDate: initialDate,
|
||||||
lastDate: DateTime(2101),
|
lastDate: DateTime(2101),
|
||||||
@@ -47,14 +48,20 @@ class _CreateTournamentPageState extends State<CreateTournamentPage> {
|
|||||||
if (!_formKey.currentState!.validate()) return;
|
if (!_formKey.currentState!.validate()) return;
|
||||||
if (_startDate == null || _endDate == null) {
|
if (_startDate == null || _endDate == null) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('Please select both start and end dates.')),
|
const SnackBar(
|
||||||
|
content: Text(
|
||||||
|
'Bitte wähle sowohl ein Start- als auch ein Enddatum aus.',
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_endDate!.isBefore(_startDate!)) {
|
if (_endDate!.isBefore(_startDate!)) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('End date cannot be before start date.')),
|
const SnackBar(
|
||||||
|
content: Text('Das Enddatum darf nicht vor dem Startdatum liegen.'),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -70,15 +77,19 @@ class _CreateTournamentPageState extends State<CreateTournamentPage> {
|
|||||||
_startDate!,
|
_startDate!,
|
||||||
_endDate!,
|
_endDate!,
|
||||||
);
|
);
|
||||||
if (!context.mounted) return;
|
if (!mounted) return;
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!context.mounted) return;
|
if (!mounted) return;
|
||||||
ScaffoldMessenger.of(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
context,
|
SnackBar(
|
||||||
).showSnackBar(SnackBar(content: Text('Error: $e')));
|
content: Text(
|
||||||
|
'Fehler: ${e.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
} finally {
|
} finally {
|
||||||
if (context.mounted) setState(() => _isLoading = false);
|
if (mounted) setState(() => _isLoading = false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -92,7 +103,7 @@ class _CreateTournamentPageState extends State<CreateTournamentPage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: const Text('Create Tournament')),
|
appBar: AppBar(title: const Text('Turnier erstellen')),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Form(
|
child: Form(
|
||||||
@@ -104,20 +115,20 @@ class _CreateTournamentPageState extends State<CreateTournamentPage> {
|
|||||||
controller: _nameController,
|
controller: _nameController,
|
||||||
decoration: const InputDecoration(labelText: 'Name'),
|
decoration: const InputDecoration(labelText: 'Name'),
|
||||||
validator: (value) =>
|
validator: (value) =>
|
||||||
value == null || value.isEmpty ? 'Required' : null,
|
value == null || value.isEmpty ? 'Pflichtfeld' : null,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
TextFormField(
|
TextFormField(
|
||||||
controller: _descriptionController,
|
controller: _descriptionController,
|
||||||
decoration: const InputDecoration(labelText: 'Description'),
|
decoration: const InputDecoration(labelText: 'Beschreibung'),
|
||||||
maxLines: 3,
|
maxLines: 3,
|
||||||
validator: (value) =>
|
validator: (value) =>
|
||||||
value == null || value.isEmpty ? 'Required' : null,
|
value == null || value.isEmpty ? 'Pflichtfeld' : null,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
DropdownButtonFormField<int>(
|
DropdownButtonFormField<int>(
|
||||||
initialValue: _maxTeamAmount,
|
initialValue: _maxTeamAmount,
|
||||||
decoration: const InputDecoration(labelText: 'Max Teams'),
|
decoration: const InputDecoration(labelText: 'Maximale Teams'),
|
||||||
items: [2, 4, 8].map((int value) {
|
items: [2, 4, 8].map((int value) {
|
||||||
return DropdownMenuItem<int>(
|
return DropdownMenuItem<int>(
|
||||||
value: value,
|
value: value,
|
||||||
@@ -140,7 +151,7 @@ class _CreateTournamentPageState extends State<CreateTournamentPage> {
|
|||||||
onPressed: () => _selectDate(context, true),
|
onPressed: () => _selectDate(context, true),
|
||||||
child: Text(
|
child: Text(
|
||||||
_startDate == null
|
_startDate == null
|
||||||
? 'Select Start Date'
|
? 'Startdatum wählen'
|
||||||
: 'Start: ${_dateFormat.format(_startDate!)}',
|
: 'Start: ${_dateFormat.format(_startDate!)}',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -151,8 +162,8 @@ class _CreateTournamentPageState extends State<CreateTournamentPage> {
|
|||||||
onPressed: () => _selectDate(context, false),
|
onPressed: () => _selectDate(context, false),
|
||||||
child: Text(
|
child: Text(
|
||||||
_endDate == null
|
_endDate == null
|
||||||
? 'Select End Date'
|
? 'Enddatum wählen'
|
||||||
: 'End: ${_dateFormat.format(_endDate!)}',
|
: 'Ende: ${_dateFormat.format(_endDate!)}',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -163,7 +174,7 @@ class _CreateTournamentPageState extends State<CreateTournamentPage> {
|
|||||||
onPressed: _isLoading ? null : _submitForm,
|
onPressed: _isLoading ? null : _submitForm,
|
||||||
child: _isLoading
|
child: _isLoading
|
||||||
? const CircularProgressIndicator()
|
? const CircularProgressIndicator()
|
||||||
: const Text('Create Tournament'),
|
: const Text('Turnier erstellen'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ class _HomePageState extends State<HomePage>
|
|||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(_selectedIndex == 0 ? "Tournaments" : "Teams"),
|
title: Text(_selectedIndex == 0 ? 'Turniere' : 'Teams'),
|
||||||
bottom: _selectedIndex == 1
|
bottom: _selectedIndex == 1
|
||||||
? TabBar(
|
? TabBar(
|
||||||
controller: _tabController,
|
controller: _tabController,
|
||||||
@@ -54,8 +54,8 @@ class _HomePageState extends State<HomePage>
|
|||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
tabs: const [
|
tabs: const [
|
||||||
Tab(text: 'All Teams'),
|
Tab(text: 'Alle Teams'),
|
||||||
Tab(text: 'My Teams'),
|
Tab(text: 'Meine Teams'),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: null,
|
: null,
|
||||||
@@ -81,7 +81,7 @@ class _HomePageState extends State<HomePage>
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(
|
content: Text(
|
||||||
'Failed to refresh ${_selectedIndex == 0 ? "tournaments" : "teams"}',
|
'Aktualisierung der ${_selectedIndex == 0 ? "Turniere" : "Teams"} fehlgeschlagen',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -95,7 +95,9 @@ class _HomePageState extends State<HomePage>
|
|||||||
},
|
},
|
||||||
offset: const Offset(0, 48),
|
offset: const Offset(0, 48),
|
||||||
itemBuilder: (context) {
|
itemBuilder: (context) {
|
||||||
return [const PopupMenuItem(value: 1, child: Text("Settings"))];
|
return [
|
||||||
|
const PopupMenuItem(value: 1, child: Text('Einstellungen')),
|
||||||
|
];
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -127,7 +129,7 @@ class _HomePageState extends State<HomePage>
|
|||||||
items: const [
|
items: const [
|
||||||
BottomNavigationBarItem(
|
BottomNavigationBarItem(
|
||||||
icon: Icon(Icons.emoji_events),
|
icon: Icon(Icons.emoji_events),
|
||||||
label: 'Tournaments',
|
label: 'Turniere',
|
||||||
),
|
),
|
||||||
BottomNavigationBarItem(icon: Icon(Icons.groups), label: 'Teams'),
|
BottomNavigationBarItem(icon: Icon(Icons.groups), label: 'Teams'),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -66,13 +66,13 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
TextFormField(
|
TextFormField(
|
||||||
controller: _usernameController,
|
controller: _usernameController,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Username',
|
labelText: 'Benutzername',
|
||||||
prefixIcon: Icon(Icons.person),
|
prefixIcon: Icon(Icons.person),
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.trim().isEmpty) {
|
if (value == null || value.trim().isEmpty) {
|
||||||
return 'Please enter a username';
|
return 'Bitte gib einen Benutzernamen ein';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
@@ -82,16 +82,16 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
controller: _passwordController,
|
controller: _passwordController,
|
||||||
obscureText: true,
|
obscureText: true,
|
||||||
decoration: const InputDecoration(
|
decoration: const InputDecoration(
|
||||||
labelText: 'Password',
|
labelText: 'Passwort',
|
||||||
prefixIcon: Icon(Icons.lock),
|
prefixIcon: Icon(Icons.lock),
|
||||||
border: OutlineInputBorder(),
|
border: OutlineInputBorder(),
|
||||||
),
|
),
|
||||||
validator: (value) {
|
validator: (value) {
|
||||||
if (value == null || value.trim().isEmpty) {
|
if (value == null || value.trim().isEmpty) {
|
||||||
return 'Please enter a password';
|
return 'Bitte gib ein Passwort ein';
|
||||||
}
|
}
|
||||||
if (_isRegistering && value.trim().length < 4) {
|
if (_isRegistering && value.trim().length < 4) {
|
||||||
return 'Password must be at least 6 characters';
|
return 'Das Passwort muss mindestens 4 Zeichen lang sein';
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
@@ -124,9 +124,13 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
? const SizedBox(
|
? const SizedBox(
|
||||||
height: 20,
|
height: 20,
|
||||||
width: 20,
|
width: 20,
|
||||||
child: CircularProgressIndicator(strokeWidth: 2),
|
child: CircularProgressIndicator(
|
||||||
|
strokeWidth: 2,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
: Text(_isRegistering ? 'Register' : 'Login'),
|
: Text(
|
||||||
|
_isRegistering ? 'Registrieren' : 'Anmelden',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -141,8 +145,8 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
_isRegistering
|
_isRegistering
|
||||||
? 'Already have an account? Login'
|
? 'Bereits ein Konto? Anmelden'
|
||||||
: 'Don\'t have an account? Register',
|
: 'Noch kein Konto? Registrieren',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -154,4 +158,3 @@ class _LoginPageState extends State<LoginPage> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,11 +17,11 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(title: Text("Splatournament")),
|
appBar: AppBar(title: const Text('Einstellungen')),
|
||||||
body: Column(
|
body: Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(height: 24),
|
const SizedBox(height: 24),
|
||||||
ProfileWidget(),
|
const ProfileWidget(),
|
||||||
Column(
|
Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@@ -29,7 +29,7 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.logout, color: Colors.red),
|
leading: const Icon(Icons.logout, color: Colors.red),
|
||||||
title: const Text(
|
title: const Text(
|
||||||
'Sign Out',
|
'Abmelden',
|
||||||
style: TextStyle(color: Colors.red),
|
style: TextStyle(color: Colors.red),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|||||||
@@ -35,13 +35,19 @@ class _TournamentBracketPageState extends State<TournamentBracketPage> {
|
|||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(content: Text('Bracket initialized successfully')),
|
const SnackBar(
|
||||||
|
content: Text('Turnierbaum erfolgreich initialisiert'),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('Failed to initialize bracket: $e')),
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
'Initialisierung des Turnierbaums fehlgeschlagen: ${e.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -51,7 +57,7 @@ class _TournamentBracketPageState extends State<TournamentBracketPage> {
|
|||||||
final result = await showDialog<int>(
|
final result = await showDialog<int>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: const Text('Select Winner'),
|
title: const Text('Sieger auswählen'),
|
||||||
content: Column(
|
content: Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
@@ -69,11 +75,11 @@ class _TournamentBracketPageState extends State<TournamentBracketPage> {
|
|||||||
if (match.hasWinner)
|
if (match.hasWinner)
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context, -1), // Reset signal
|
onPressed: () => Navigator.pop(context, -1), // Reset signal
|
||||||
child: const Text('Reset'),
|
child: const Text('Zurücksetzen'),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
child: const Text('Cancel'),
|
child: const Text('Abbrechen'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -91,14 +97,22 @@ class _TournamentBracketPageState extends State<TournamentBracketPage> {
|
|||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(result == -1 ? 'Match reset' : 'Winner set successfully'),
|
content: Text(
|
||||||
|
result == -1
|
||||||
|
? 'Match zurückgesetzt'
|
||||||
|
: 'Sieger erfolgreich festgelegt',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('Error: $e')),
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
'Fehler: ${e.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -122,7 +136,11 @@ class _TournamentBracketPageState extends State<TournamentBracketPage> {
|
|||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
return Center(child: Text('Error: ${snapshot.error}'));
|
return Center(
|
||||||
|
child: Text(
|
||||||
|
'Fehler: ${snapshot.error.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final teams = snapshot.data![0] as List<Team>;
|
final teams = snapshot.data![0] as List<Team>;
|
||||||
@@ -135,19 +153,19 @@ class _TournamentBracketPageState extends State<TournamentBracketPage> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
const Text(
|
||||||
'Bracket not initialized yet',
|
'Der Turnierbaum wurde noch nicht initialisiert',
|
||||||
style: TextStyle(fontSize: 18),
|
style: TextStyle(fontSize: 18),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: teams.length >= 2 ? _initializeBracket : null,
|
onPressed: teams.length >= 2 ? _initializeBracket : null,
|
||||||
child: const Text('Initialize Bracket'),
|
child: const Text('Turnierbaum initialisieren'),
|
||||||
),
|
),
|
||||||
if (teams.length < 2)
|
if (teams.length < 2)
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.only(top: 8),
|
padding: EdgeInsets.only(top: 8),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Need at least 2 teams',
|
'Mindestens 2 Teams erforderlich',
|
||||||
style: TextStyle(color: Colors.red),
|
style: TextStyle(color: Colors.red),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -208,11 +226,11 @@ class _BracketBoard extends StatelessWidget {
|
|||||||
});
|
});
|
||||||
|
|
||||||
String _roundLabel(int round) {
|
String _roundLabel(int round) {
|
||||||
if (round == roundCount - 1) return 'Winner';
|
if (round == roundCount - 1) return 'Sieger';
|
||||||
final teamsInRound = bracketSize ~/ (1 << round);
|
final teamsInRound = bracketSize ~/ (1 << round);
|
||||||
if (teamsInRound == 2) return 'Final';
|
if (teamsInRound == 2) return 'Finale';
|
||||||
if (teamsInRound == 4) return 'Semi-finals';
|
if (teamsInRound == 4) return 'Halbfinale';
|
||||||
return 'Quarter-finals';
|
return 'Viertelfinale';
|
||||||
}
|
}
|
||||||
|
|
||||||
double _cardTop(int round, int index) {
|
double _cardTop(int round, int index) {
|
||||||
@@ -376,11 +394,7 @@ class _MatchCard extends StatelessWidget {
|
|||||||
final Map<int, Team> teamMap;
|
final Map<int, Team> teamMap;
|
||||||
final VoidCallback? onTap;
|
final VoidCallback? onTap;
|
||||||
|
|
||||||
const _MatchCard({
|
const _MatchCard({this.match, required this.teamMap, this.onTap});
|
||||||
this.match,
|
|
||||||
required this.teamMap,
|
|
||||||
this.onTap,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -430,7 +444,7 @@ class _MatchCard extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
Text(
|
Text(
|
||||||
'vs',
|
'vs.',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 10,
|
fontSize: 10,
|
||||||
color: colorScheme.onSurface.withValues(alpha: 0.6),
|
color: colorScheme.onSurface.withValues(alpha: 0.6),
|
||||||
|
|||||||
@@ -3,8 +3,15 @@ import 'package:frontend_splatournament_manager/models/team.dart';
|
|||||||
import 'package:frontend_splatournament_manager/models/tournament.dart';
|
import 'package:frontend_splatournament_manager/models/tournament.dart';
|
||||||
import 'package:frontend_splatournament_manager/pages/tournament_bracket_page.dart';
|
import 'package:frontend_splatournament_manager/pages/tournament_bracket_page.dart';
|
||||||
import 'package:frontend_splatournament_manager/providers/team_provider.dart';
|
import 'package:frontend_splatournament_manager/providers/team_provider.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
|
final DateFormat _tournamentDateFormat = DateFormat('dd.MM.yyyy', 'de_DE');
|
||||||
|
|
||||||
|
String _formatTournamentDate(String value) {
|
||||||
|
return _tournamentDateFormat.format(DateTime.parse(value));
|
||||||
|
}
|
||||||
|
|
||||||
class TournamentDetailPage extends StatefulWidget {
|
class TournamentDetailPage extends StatefulWidget {
|
||||||
final Tournament tournament;
|
final Tournament tournament;
|
||||||
|
|
||||||
@@ -29,7 +36,7 @@ class _TournamentDetailPageState extends State<TournamentDetailPage> {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
const SnackBar(
|
||||||
content: Text(
|
content: Text(
|
||||||
'You are not a member of any team. Join or create a team first!',
|
'Du bist in keinem Team. Tritt zuerst einem Team bei oder erstelle eines.',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -40,7 +47,7 @@ class _TournamentDetailPageState extends State<TournamentDetailPage> {
|
|||||||
context: context,
|
context: context,
|
||||||
builder: (BuildContext dialogContext) {
|
builder: (BuildContext dialogContext) {
|
||||||
return AlertDialog(
|
return AlertDialog(
|
||||||
title: const Text('Select Your Team'),
|
title: const Text('Team auswählen'),
|
||||||
content: SizedBox(
|
content: SizedBox(
|
||||||
width: double.maxFinite,
|
width: double.maxFinite,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
@@ -62,7 +69,7 @@ class _TournamentDetailPageState extends State<TournamentDetailPage> {
|
|||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(dialogContext),
|
onPressed: () => Navigator.pop(dialogContext),
|
||||||
child: const Text('Cancel'),
|
child: const Text('Abbrechen'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
@@ -80,7 +87,9 @@ class _TournamentDetailPageState extends State<TournamentDetailPage> {
|
|||||||
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('${selectedTeam.name} joined the tournament!'),
|
content: Text(
|
||||||
|
'${selectedTeam.name} wurde für das Turnier angemeldet.',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -93,7 +102,7 @@ class _TournamentDetailPageState extends State<TournamentDetailPage> {
|
|||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text(
|
content: Text(
|
||||||
'Failed to join: ${e.toString().replaceAll('Exception: ', '')}',
|
'Anmeldung fehlgeschlagen: ${e.toString().replaceAll('Exception: ', '')}',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -101,9 +110,13 @@ class _TournamentDetailPageState extends State<TournamentDetailPage> {
|
|||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
context,
|
SnackBar(
|
||||||
).showSnackBar(SnackBar(content: Text('Failed to load your teams: $e')));
|
content: Text(
|
||||||
|
'Deine Teams konnten nicht geladen werden: ${e.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -161,10 +174,10 @@ class _TournamentDetailPageState extends State<TournamentDetailPage> {
|
|||||||
: null,
|
: null,
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.tournament.isRegistrationFuture
|
widget.tournament.isRegistrationFuture
|
||||||
? "Registration not open yet"
|
? 'Anmeldung noch nicht geöffnet'
|
||||||
: widget.tournament.isRegistrationPast
|
: widget.tournament.isRegistrationPast
|
||||||
? "Registration closed"
|
? 'Anmeldung geschlossen'
|
||||||
: "Join with Team",
|
: 'Mit Team anmelden',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -205,7 +218,7 @@ class _TournamentTeamsWidgetState extends State<TournamentTeamsWidget> {
|
|||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(16, 12, 16, 4),
|
padding: const EdgeInsets.fromLTRB(16, 12, 16, 4),
|
||||||
child: Text(
|
child: Text(
|
||||||
'Registered Teams',
|
'Angemeldete Teams',
|
||||||
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 17),
|
style: TextStyle(fontWeight: FontWeight.w600, fontSize: 17),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -217,11 +230,17 @@ class _TournamentTeamsWidgetState extends State<TournamentTeamsWidget> {
|
|||||||
return Center(child: CircularProgressIndicator());
|
return Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
return Center(child: Text('Error: ${snapshot.error}'));
|
return Center(
|
||||||
|
child: Text(
|
||||||
|
'Fehler: ${snapshot.error.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
final teams = snapshot.data ?? [];
|
final teams = snapshot.data ?? [];
|
||||||
if (teams.isEmpty) {
|
if (teams.isEmpty) {
|
||||||
return Center(child: Text('No teams registered yet.'));
|
return const Center(
|
||||||
|
child: Text('Noch keine Teams angemeldet.'),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
itemCount: teams.length,
|
itemCount: teams.length,
|
||||||
@@ -257,7 +276,9 @@ class _TournamentTeamsWidgetState extends State<TournamentTeamsWidget> {
|
|||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(
|
SnackBar(
|
||||||
content: Text('Failed to remove team: $e'),
|
content: Text(
|
||||||
|
'Team konnte nicht entfernt werden: ${e.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -282,6 +303,9 @@ class TournamentContentWidget extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
final registrationPeriod =
|
||||||
|
'${_formatTournamentDate(tournament.registrationStartDate)} - ${_formatTournamentDate(tournament.registrationEndDate)}';
|
||||||
|
|
||||||
return Expanded(
|
return Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -300,24 +324,22 @@ class TournamentContentWidget extends StatelessWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Registration Period",
|
'Anmeldezeitraum',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 17,
|
fontSize: 17,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(registrationPeriod),
|
||||||
"${tournament.registrationStartDate} - ${tournament.registrationEndDate}",
|
|
||||||
),
|
|
||||||
SizedBox(height: 24),
|
SizedBox(height: 24),
|
||||||
Text(
|
Text(
|
||||||
"Format",
|
'Format',
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.w600,
|
fontWeight: FontWeight.w600,
|
||||||
fontSize: 17,
|
fontSize: 17,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text("Single Elimination"),
|
const Text('Einfaches K.-o.-System'),
|
||||||
Spacer(),
|
Spacer(),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
@@ -331,7 +353,7 @@ class TournamentContentWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Text("View ongoing"),
|
child: const Text('Turnierbaum ansehen'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -382,7 +404,7 @@ class DetailHeader extends StatelessWidget {
|
|||||||
InputChip(
|
InputChip(
|
||||||
onPressed: () => onTeamsChipClicked(),
|
onPressed: () => onTeamsChipClicked(),
|
||||||
label: Text(
|
label: Text(
|
||||||
"${tournament.currentTeamAmount} out of ${tournament.maxTeamAmount} Teams",
|
'${tournament.currentTeamAmount} von ${tournament.maxTeamAmount} Teams',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -7,10 +7,15 @@ import 'package:frontend_splatournament_manager/services/api_client.dart';
|
|||||||
|
|
||||||
class MatchProvider extends ChangeNotifier {
|
class MatchProvider extends ChangeNotifier {
|
||||||
Future<void> initializeBracket(int tournamentId) async {
|
Future<void> initializeBracket(int tournamentId) async {
|
||||||
final response = await ApiClient.post('/tournaments/$tournamentId/bracket', {});
|
final response = await ApiClient.post(
|
||||||
|
'/tournaments/$tournamentId/bracket',
|
||||||
|
{},
|
||||||
|
);
|
||||||
|
|
||||||
if (response.statusCode != HttpStatus.created) {
|
if (response.statusCode != HttpStatus.created) {
|
||||||
throw Exception('Failed to initialize bracket (${response.statusCode})');
|
throw Exception(
|
||||||
|
'Turnierbaum konnte nicht initialisiert werden (${response.statusCode})',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@@ -20,7 +25,9 @@ class MatchProvider extends ChangeNotifier {
|
|||||||
final response = await ApiClient.get('/tournaments/$tournamentId/matches');
|
final response = await ApiClient.get('/tournaments/$tournamentId/matches');
|
||||||
|
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
throw Exception('Failed to load matches (${response.statusCode})');
|
throw Exception(
|
||||||
|
'Matches konnten nicht geladen werden (${response.statusCode})',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<dynamic> list = json.decode(response.body);
|
final List<dynamic> list = json.decode(response.body);
|
||||||
@@ -34,7 +41,9 @@ class MatchProvider extends ChangeNotifier {
|
|||||||
|
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
final error = json.decode(response.body);
|
final error = json.decode(response.body);
|
||||||
throw Exception(error['error'] ?? 'Failed to set winner');
|
throw Exception(
|
||||||
|
error['error'] ?? 'Sieger konnte nicht festgelegt werden',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
@@ -44,7 +53,9 @@ class MatchProvider extends ChangeNotifier {
|
|||||||
final response = await ApiClient.delete('/matches/$matchId/winner');
|
final response = await ApiClient.delete('/matches/$matchId/winner');
|
||||||
|
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
throw Exception('Failed to reset match (${response.statusCode})');
|
throw Exception(
|
||||||
|
'Match konnte nicht zurückgesetzt werden (${response.statusCode})',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
notifyListeners();
|
notifyListeners();
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ import 'package:frontend_splatournament_manager/models/tournament.dart';
|
|||||||
import 'package:frontend_splatournament_manager/services/api_client.dart';
|
import 'package:frontend_splatournament_manager/services/api_client.dart';
|
||||||
|
|
||||||
class TournamentProvider extends ChangeNotifier {
|
class TournamentProvider extends ChangeNotifier {
|
||||||
|
|
||||||
List<Tournament> _availableTournaments = [];
|
List<Tournament> _availableTournaments = [];
|
||||||
Future<List<Tournament>>? _initialLoadFuture;
|
Future<List<Tournament>>? _initialLoadFuture;
|
||||||
|
|
||||||
@@ -15,7 +14,9 @@ class TournamentProvider extends ChangeNotifier {
|
|||||||
Future<List<Tournament>> _fetchTournaments() async {
|
Future<List<Tournament>> _fetchTournaments() async {
|
||||||
final response = await ApiClient.get('/tournaments');
|
final response = await ApiClient.get('/tournaments');
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
throw Exception('Failed to load tournaments (${response.statusCode})');
|
throw Exception(
|
||||||
|
'Turniere konnten nicht geladen werden (${response.statusCode})',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<dynamic> list = json.decode(response.body);
|
final List<dynamic> list = json.decode(response.body);
|
||||||
@@ -45,19 +46,22 @@ class TournamentProvider extends ChangeNotifier {
|
|||||||
DateTime registrationStartDate,
|
DateTime registrationStartDate,
|
||||||
DateTime registrationEndDate,
|
DateTime registrationEndDate,
|
||||||
) async {
|
) async {
|
||||||
final response = await ApiClient.post(
|
final response = await ApiClient.post('/tournaments', {
|
||||||
'/tournaments',
|
|
||||||
{
|
|
||||||
'name': name,
|
'name': name,
|
||||||
'description': description,
|
'description': description,
|
||||||
'maxTeamAmount': maxTeamAmount,
|
'maxTeamAmount': maxTeamAmount,
|
||||||
'registrationStartDate': registrationStartDate.toIso8601String().split('T')[0],
|
'registrationStartDate': registrationStartDate.toIso8601String().split(
|
||||||
'registrationEndDate': registrationEndDate.toIso8601String().split('T')[0],
|
'T',
|
||||||
},
|
)[0],
|
||||||
);
|
'registrationEndDate': registrationEndDate.toIso8601String().split(
|
||||||
|
'T',
|
||||||
|
)[0],
|
||||||
|
});
|
||||||
|
|
||||||
if (response.statusCode != HttpStatus.created) {
|
if (response.statusCode != HttpStatus.created) {
|
||||||
throw Exception('Failed to create tournament (${response.statusCode})');
|
throw Exception(
|
||||||
|
'Turnier konnte nicht erstellt werden (${response.statusCode})',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
await refreshAvailableTournaments();
|
await refreshAvailableTournaments();
|
||||||
|
|||||||
@@ -4,7 +4,10 @@ import 'package:http/http.dart' as http;
|
|||||||
|
|
||||||
class AuthService {
|
class AuthService {
|
||||||
final String baseUrl = SplatournamentApp.baseUrl;
|
final String baseUrl = SplatournamentApp.baseUrl;
|
||||||
Future<Map<String, dynamic>> register(String username, String password) async {
|
Future<Map<String, dynamic>> register(
|
||||||
|
String username,
|
||||||
|
String password,
|
||||||
|
) async {
|
||||||
final response = await http.post(
|
final response = await http.post(
|
||||||
Uri.parse('$baseUrl/register'),
|
Uri.parse('$baseUrl/register'),
|
||||||
headers: {'Content-Type': 'application/json'},
|
headers: {'Content-Type': 'application/json'},
|
||||||
@@ -15,7 +18,7 @@ class AuthService {
|
|||||||
return json.decode(response.body);
|
return json.decode(response.body);
|
||||||
} else {
|
} else {
|
||||||
final body = json.decode(response.body);
|
final body = json.decode(response.body);
|
||||||
throw Exception(body['error'] ?? 'Registration failed');
|
throw Exception(body['error'] ?? 'Registrierung fehlgeschlagen');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,8 +33,7 @@ class AuthService {
|
|||||||
return json.decode(response.body);
|
return json.decode(response.body);
|
||||||
} else {
|
} else {
|
||||||
final body = json.decode(response.body);
|
final body = json.decode(response.body);
|
||||||
throw Exception(body['error'] ?? 'Login failed');
|
throw Exception(body['error'] ?? 'Anmeldung fehlgeschlagen');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,12 @@ import 'package:frontend_splatournament_manager/models/team.dart';
|
|||||||
import 'package:frontend_splatournament_manager/services/api_client.dart';
|
import 'package:frontend_splatournament_manager/services/api_client.dart';
|
||||||
|
|
||||||
class TeamService {
|
class TeamService {
|
||||||
|
|
||||||
Future<List<Team>> getAllTeams() async {
|
Future<List<Team>> getAllTeams() async {
|
||||||
final response = await ApiClient.get('/teams');
|
final response = await ApiClient.get('/teams');
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
throw Exception('Failed to load teams (${response.statusCode})');
|
throw Exception(
|
||||||
|
'Teams konnten nicht geladen werden (${response.statusCode})',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
final List<dynamic> list = json.decode(response.body);
|
final List<dynamic> list = json.decode(response.body);
|
||||||
return list.map((j) => Team.fromJson(j as Map<String, dynamic>)).toList();
|
return list.map((j) => Team.fromJson(j as Map<String, dynamic>)).toList();
|
||||||
@@ -18,10 +19,12 @@ class TeamService {
|
|||||||
Future<Team> getTeamById(int id) async {
|
Future<Team> getTeamById(int id) async {
|
||||||
final response = await ApiClient.get('/teams/$id');
|
final response = await ApiClient.get('/teams/$id');
|
||||||
if (response.statusCode == HttpStatus.notFound) {
|
if (response.statusCode == HttpStatus.notFound) {
|
||||||
throw Exception('Team not found');
|
throw Exception('Team nicht gefunden');
|
||||||
}
|
}
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
throw Exception('Failed to load team (${response.statusCode})');
|
throw Exception(
|
||||||
|
'Team konnte nicht geladen werden (${response.statusCode})',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return Team.fromJson(json.decode(response.body) as Map<String, dynamic>);
|
return Team.fromJson(json.decode(response.body) as Map<String, dynamic>);
|
||||||
}
|
}
|
||||||
@@ -31,13 +34,14 @@ class TeamService {
|
|||||||
required String tag,
|
required String tag,
|
||||||
String description = '',
|
String description = '',
|
||||||
}) async {
|
}) async {
|
||||||
final response = await ApiClient.post(
|
final response = await ApiClient.post('/teams', {
|
||||||
'/teams',
|
'name': name,
|
||||||
{'name': name, 'tag': tag, 'description': description},
|
'tag': tag,
|
||||||
);
|
'description': description,
|
||||||
|
});
|
||||||
if (response.statusCode != HttpStatus.created) {
|
if (response.statusCode != HttpStatus.created) {
|
||||||
final body = json.decode(response.body);
|
final body = json.decode(response.body);
|
||||||
throw Exception(body['error'] ?? 'Failed to create team');
|
throw Exception(body['error'] ?? 'Team konnte nicht erstellt werden');
|
||||||
}
|
}
|
||||||
return Team.fromJson(json.decode(response.body) as Map<String, dynamic>);
|
return Team.fromJson(json.decode(response.body) as Map<String, dynamic>);
|
||||||
}
|
}
|
||||||
@@ -48,17 +52,14 @@ class TeamService {
|
|||||||
String? tag,
|
String? tag,
|
||||||
String? description,
|
String? description,
|
||||||
}) async {
|
}) async {
|
||||||
final response = await ApiClient.put(
|
final response = await ApiClient.put('/teams/$id', {
|
||||||
'/teams/$id',
|
'name': name,
|
||||||
{
|
'tag': tag,
|
||||||
if (name != null) 'name': name,
|
'description': description,
|
||||||
if (tag != null) 'tag': tag,
|
});
|
||||||
if (description != null) 'description': description,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
final body = json.decode(response.body);
|
final body = json.decode(response.body);
|
||||||
throw Exception(body['error'] ?? 'Failed to update team');
|
throw Exception(body['error'] ?? 'Team konnte nicht aktualisiert werden');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,7 +67,7 @@ class TeamService {
|
|||||||
final response = await ApiClient.delete('/teams/$id');
|
final response = await ApiClient.delete('/teams/$id');
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
final body = json.decode(response.body);
|
final body = json.decode(response.body);
|
||||||
throw Exception(body['error'] ?? 'Failed to delete team');
|
throw Exception(body['error'] ?? 'Team konnte nicht gelöscht werden');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +75,7 @@ class TeamService {
|
|||||||
final response = await ApiClient.get('/tournaments/$tournamentId/teams');
|
final response = await ApiClient.get('/tournaments/$tournamentId/teams');
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'Failed to load teams for tournament (${response.statusCode})',
|
'Teams für das Turnier konnten nicht geladen werden (${response.statusCode})',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
final List<dynamic> list = json.decode(response.body);
|
final List<dynamic> list = json.decode(response.body);
|
||||||
@@ -82,24 +83,29 @@ class TeamService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> registerTeamForTournament(int tournamentId, int teamId) async {
|
Future<void> registerTeamForTournament(int tournamentId, int teamId) async {
|
||||||
final response = await ApiClient.post(
|
final response = await ApiClient.post('/tournaments/$tournamentId/teams', {
|
||||||
'/tournaments/$tournamentId/teams',
|
'teamId': teamId,
|
||||||
{'teamId': teamId},
|
});
|
||||||
);
|
|
||||||
if (response.statusCode == 409) {
|
if (response.statusCode == 409) {
|
||||||
throw Exception('Team is already registered for this tournament');
|
throw Exception('Das Team ist bereits für dieses Turnier angemeldet');
|
||||||
}
|
}
|
||||||
if (response.statusCode != HttpStatus.created) {
|
if (response.statusCode != HttpStatus.created) {
|
||||||
final body = json.decode(response.body);
|
final body = json.decode(response.body);
|
||||||
throw Exception(body['error'] ?? 'Failed to register team');
|
throw Exception(
|
||||||
|
body['error'] ?? 'Team konnte nicht für das Turnier angemeldet werden',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> removeTeamFromTournament(int tournamentId, int teamId) async {
|
Future<void> removeTeamFromTournament(int tournamentId, int teamId) async {
|
||||||
final response = await ApiClient.delete('/tournaments/$tournamentId/teams/$teamId');
|
final response = await ApiClient.delete(
|
||||||
|
'/tournaments/$tournamentId/teams/$teamId',
|
||||||
|
);
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
final body = json.decode(response.body);
|
final body = json.decode(response.body);
|
||||||
throw Exception(body['error'] ?? 'Failed to remove team from tournament');
|
throw Exception(
|
||||||
|
body['error'] ?? 'Team konnte nicht aus dem Turnier entfernt werden',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +113,7 @@ class TeamService {
|
|||||||
final response = await ApiClient.get('/teams/$teamId/tournaments');
|
final response = await ApiClient.get('/teams/$teamId/tournaments');
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
throw Exception(
|
throw Exception(
|
||||||
'Failed to load tournaments for team (${response.statusCode})',
|
'Turniere für das Team konnten nicht geladen werden (${response.statusCode})',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
final List<dynamic> list = json.decode(response.body);
|
final List<dynamic> list = json.decode(response.body);
|
||||||
@@ -117,7 +123,9 @@ class TeamService {
|
|||||||
Future<List<Team>> getUserTeams() async {
|
Future<List<Team>> getUserTeams() async {
|
||||||
final response = await ApiClient.get('/users/me/teams');
|
final response = await ApiClient.get('/users/me/teams');
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
throw Exception('Failed to load user teams (${response.statusCode})');
|
throw Exception(
|
||||||
|
'Eigene Teams konnten nicht geladen werden (${response.statusCode})',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
final List<dynamic> list = json.decode(response.body);
|
final List<dynamic> list = json.decode(response.body);
|
||||||
return list.map((j) => Team.fromJson(j as Map<String, dynamic>)).toList();
|
return list.map((j) => Team.fromJson(j as Map<String, dynamic>)).toList();
|
||||||
@@ -126,11 +134,11 @@ class TeamService {
|
|||||||
Future<void> joinTeam(int teamId) async {
|
Future<void> joinTeam(int teamId) async {
|
||||||
final response = await ApiClient.post('/teams/$teamId/members', {});
|
final response = await ApiClient.post('/teams/$teamId/members', {});
|
||||||
if (response.statusCode == 409) {
|
if (response.statusCode == 409) {
|
||||||
throw Exception('You are already a member of this team');
|
throw Exception('Du bist bereits Mitglied dieses Teams');
|
||||||
}
|
}
|
||||||
if (response.statusCode != HttpStatus.created) {
|
if (response.statusCode != HttpStatus.created) {
|
||||||
final body = json.decode(response.body);
|
final body = json.decode(response.body);
|
||||||
throw Exception(body['error'] ?? 'Failed to join team');
|
throw Exception(body['error'] ?? 'Beitritt zum Team fehlgeschlagen');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,14 +146,16 @@ class TeamService {
|
|||||||
final response = await ApiClient.delete('/teams/$teamId/members/me');
|
final response = await ApiClient.delete('/teams/$teamId/members/me');
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
final body = json.decode(response.body);
|
final body = json.decode(response.body);
|
||||||
throw Exception(body['error'] ?? 'Failed to leave team');
|
throw Exception(body['error'] ?? 'Team konnte nicht verlassen werden');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Map<String, dynamic>>> getTeamMembers(int teamId) async {
|
Future<List<Map<String, dynamic>>> getTeamMembers(int teamId) async {
|
||||||
final response = await ApiClient.get('/teams/$teamId/members');
|
final response = await ApiClient.get('/teams/$teamId/members');
|
||||||
if (response.statusCode != HttpStatus.ok) {
|
if (response.statusCode != HttpStatus.ok) {
|
||||||
throw Exception('Failed to load team members (${response.statusCode})');
|
throw Exception(
|
||||||
|
'Teammitglieder konnten nicht geladen werden (${response.statusCode})',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
final List<dynamic> list = json.decode(response.body);
|
final List<dynamic> list = json.decode(response.body);
|
||||||
return list.cast<Map<String, dynamic>>();
|
return list.cast<Map<String, dynamic>>();
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class AvailableTournamentList extends StatelessWidget {
|
|||||||
padding: EdgeInsets.fromLTRB(24, 0, 24, 0),
|
padding: EdgeInsets.fromLTRB(24, 0, 24, 0),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Row(children: [Text("Available Tournaments")]),
|
const Row(children: [Text('Verfügbare Turniere')]),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: double.infinity,
|
width: double.infinity,
|
||||||
height: 350,
|
height: 350,
|
||||||
@@ -40,18 +40,21 @@ class TournamentListFutureBuilder extends StatelessWidget {
|
|||||||
future: provider.ensureTournamentsLoaded(),
|
future: provider.ensureTournamentsLoaded(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final list = provider.availableTournaments;
|
final list = provider.availableTournaments;
|
||||||
print(list);
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting &&
|
if (snapshot.connectionState == ConnectionState.waiting &&
|
||||||
list.isEmpty) {
|
list.isEmpty) {
|
||||||
return Center(child: CircularProgressIndicator());
|
return Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snapshot.hasError && list.isEmpty) {
|
if (snapshot.hasError && list.isEmpty) {
|
||||||
return Center(child: Text('Error: ${snapshot.error}'));
|
return Center(
|
||||||
|
child: Text(
|
||||||
|
'Fehler: ${snapshot.error.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (list.isEmpty) {
|
if (list.isEmpty) {
|
||||||
return Center(child: Text('No tournaments found'));
|
return const Center(child: Text('Keine Turniere gefunden'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
|
|||||||
@@ -20,7 +20,10 @@ class _MyTeamsWidgetState extends State<MyTeamsWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _loadMyTeams() {
|
void _loadMyTeams() {
|
||||||
_myTeamsFuture = Provider.of<TeamProvider>(context, listen: false).getUserTeams();
|
_myTeamsFuture = Provider.of<TeamProvider>(
|
||||||
|
context,
|
||||||
|
listen: false,
|
||||||
|
).getUserTeams();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -33,13 +36,19 @@ class _MyTeamsWidgetState extends State<MyTeamsWidget> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
return Center(child: Text('Error: ${snapshot.error}'));
|
return Center(
|
||||||
|
child: Text(
|
||||||
|
'Fehler: ${snapshot.error.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final teams = snapshot.data ?? [];
|
final teams = snapshot.data ?? [];
|
||||||
if (teams.isEmpty) {
|
if (teams.isEmpty) {
|
||||||
return const Center(
|
return const Center(
|
||||||
child: Text('You are not in any teams yet\nJoin teams from the All Teams tab'),
|
child: Text(
|
||||||
|
'Du bist noch in keinem Team.\nTritt einem Team im Tab Alle Teams bei.',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,9 +63,11 @@ class _MyTeamsWidgetState extends State<MyTeamsWidget> {
|
|||||||
|
|
||||||
Widget _buildTeamCard(Team team) {
|
Widget _buildTeamCard(Team team) {
|
||||||
final memberCountText = team.memberCount != null
|
final memberCountText = team.memberCount != null
|
||||||
? '${team.memberCount}/4 members'
|
? '${team.memberCount}/4 Mitglieder'
|
||||||
: 'No members';
|
: 'Keine Mitglieder';
|
||||||
final description = team.description.isEmpty ? 'No description' : team.description;
|
final description = team.description.isEmpty
|
||||||
|
? 'Keine Beschreibung'
|
||||||
|
: team.description;
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
@@ -79,16 +90,16 @@ class _MyTeamsWidgetState extends State<MyTeamsWidget> {
|
|||||||
final confirmed = await showDialog<bool>(
|
final confirmed = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: const Text('Leave Team?'),
|
title: const Text('Team verlassen?'),
|
||||||
content: Text('Leave "${team.name}"?'),
|
content: Text('Soll "${team.name}" verlassen werden?'),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context, false),
|
onPressed: () => Navigator.pop(context, false),
|
||||||
child: const Text('Cancel'),
|
child: const Text('Abbrechen'),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context, true),
|
onPressed: () => Navigator.pop(context, true),
|
||||||
child: const Text('Leave', style: TextStyle(color: Colors.red)),
|
child: const Text('Verlassen', style: TextStyle(color: Colors.red)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -96,18 +107,25 @@ class _MyTeamsWidgetState extends State<MyTeamsWidget> {
|
|||||||
|
|
||||||
if (confirmed == true && mounted) {
|
if (confirmed == true && mounted) {
|
||||||
try {
|
try {
|
||||||
await Provider.of<TeamProvider>(context, listen: false).leaveTeam(team.id);
|
await Provider.of<TeamProvider>(
|
||||||
|
context,
|
||||||
|
listen: false,
|
||||||
|
).leaveTeam(team.id);
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(
|
||||||
const SnackBar(content: Text('Left team')),
|
context,
|
||||||
);
|
).showSnackBar(const SnackBar(content: Text('Team verlassen')));
|
||||||
_loadMyTeams();
|
_loadMyTeams();
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('Error: $e')),
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
'Fehler: ${e.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ class _MyTournamentsCarouselState extends State<MyTournamentsCarousel> {
|
|||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(16, 16, 16, 8),
|
padding: EdgeInsets.fromLTRB(16, 16, 16, 8),
|
||||||
child: Text(
|
child: Text(
|
||||||
'My Tournaments',
|
'Meine Turniere',
|
||||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -58,7 +58,7 @@ class _MyTournamentsCarouselState extends State<MyTournamentsCarousel> {
|
|||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
const Text(
|
const Text(
|
||||||
'No tournaments found',
|
'Keine Turniere gefunden',
|
||||||
style: TextStyle(fontSize: 16, color: Colors.grey),
|
style: TextStyle(fontSize: 16, color: Colors.grey),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -77,7 +77,7 @@ class _MyTournamentsCarouselState extends State<MyTournamentsCarousel> {
|
|||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.fromLTRB(16, 16, 16, 8),
|
padding: EdgeInsets.fromLTRB(16, 16, 16, 8),
|
||||||
child: Text(
|
child: Text(
|
||||||
'My Tournaments',
|
'Meine Turniere',
|
||||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -162,13 +162,13 @@ class _TournamentCard extends StatelessWidget {
|
|||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Text(
|
Text(
|
||||||
tournament.isRegistrationOpen
|
tournament.isRegistrationOpen
|
||||||
? 'Registration Open'
|
? 'Anmeldung offen'
|
||||||
: 'Registration Closed',
|
: 'Anmeldung geschlossen',
|
||||||
style: const TextStyle(fontSize: 14),
|
style: const TextStyle(fontSize: 14),
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
Text(
|
Text(
|
||||||
'${tournament.currentTeamAmount}/${tournament.maxTeamAmount} teams',
|
'${tournament.currentTeamAmount}/${tournament.maxTeamAmount} Teams',
|
||||||
style: const TextStyle(fontSize: 14),
|
style: const TextStyle(fontSize: 14),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ class _ProfileWidgetState extends State<ProfileWidget> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Consumer<AuthProvider>(
|
return Consumer<AuthProvider>(
|
||||||
builder: (context, provider, child) {
|
builder: (context, provider, child) {
|
||||||
final username = provider.username ?? "Unknown User";
|
final username = provider.username ?? 'Unbekannter Benutzer';
|
||||||
final avatarText = username.length >= 3
|
final avatarText = username.length >= 3
|
||||||
? username.substring(0, 3).toUpperCase()
|
? username.substring(0, 3).toUpperCase()
|
||||||
: username.toUpperCase();
|
: username.toUpperCase();
|
||||||
|
|||||||
@@ -18,21 +18,27 @@ class TeamsListWidget extends StatelessWidget {
|
|||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final teams = provider.teams;
|
final teams = provider.teams;
|
||||||
|
|
||||||
if (snapshot.connectionState == ConnectionState.waiting && teams.isEmpty) {
|
if (snapshot.connectionState == ConnectionState.waiting &&
|
||||||
|
teams.isEmpty) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (snapshot.hasError && teams.isEmpty) {
|
if (snapshot.hasError && teams.isEmpty) {
|
||||||
return Center(child: Text('Error: ${snapshot.error}'));
|
return Center(
|
||||||
|
child: Text(
|
||||||
|
'Fehler: ${snapshot.error.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (teams.isEmpty) {
|
if (teams.isEmpty) {
|
||||||
return const Center(child: Text('No teams found'));
|
return const Center(child: Text('Keine Teams gefunden'));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
itemCount: teams.length,
|
itemCount: teams.length,
|
||||||
itemBuilder: (context, index) => TeamListItem(team: teams[index]),
|
itemBuilder: (context, index) =>
|
||||||
|
TeamListItem(team: teams[index]),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -50,9 +56,11 @@ class TeamListItem extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final memberCountText = team.memberCount != null
|
final memberCountText = team.memberCount != null
|
||||||
? '${team.memberCount}/4 members'
|
? '${team.memberCount}/4 Mitglieder'
|
||||||
: 'No members';
|
: 'Keine Mitglieder';
|
||||||
final description = team.description.isEmpty ? 'No description' : team.description;
|
final description = team.description.isEmpty
|
||||||
|
? 'Keine Beschreibung'
|
||||||
|
: team.description;
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
@@ -66,11 +74,11 @@ class TeamListItem extends StatelessWidget {
|
|||||||
trailing: PopupMenuButton(
|
trailing: PopupMenuButton(
|
||||||
icon: const Icon(Icons.more_vert),
|
icon: const Icon(Icons.more_vert),
|
||||||
itemBuilder: (context) => [
|
itemBuilder: (context) => [
|
||||||
const PopupMenuItem(value: 'join', child: Text('Join Team')),
|
const PopupMenuItem(value: 'join', child: Text('Team beitreten')),
|
||||||
const PopupMenuItem(value: 'edit', child: Text('Edit Team')),
|
const PopupMenuItem(value: 'edit', child: Text('Team bearbeiten')),
|
||||||
const PopupMenuItem(
|
const PopupMenuItem(
|
||||||
value: 'delete',
|
value: 'delete',
|
||||||
child: Text('Delete Team', style: TextStyle(color: Colors.red)),
|
child: Text('Team löschen', style: TextStyle(color: Colors.red)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
onSelected: (value) async {
|
onSelected: (value) async {
|
||||||
@@ -98,7 +106,7 @@ class TeamListItem extends StatelessWidget {
|
|||||||
await Provider.of<TeamProvider>(context, listen: false).joinTeam(team.id);
|
await Provider.of<TeamProvider>(context, listen: false).joinTeam(team.id);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('Joined ${team.name}!')),
|
SnackBar(content: Text('Du bist ${team.name} beigetreten.')),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
@@ -114,16 +122,18 @@ class TeamListItem extends StatelessWidget {
|
|||||||
final confirmed = await showDialog<bool>(
|
final confirmed = await showDialog<bool>(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: const Text('Delete Team?'),
|
title: const Text('Team löschen?'),
|
||||||
content: Text('Delete "${team.name}"? This cannot be undone.'),
|
content: Text(
|
||||||
|
'Soll "${team.name}" gelöscht werden? Das kann nicht rückgängig gemacht werden.',
|
||||||
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context, false),
|
onPressed: () => Navigator.pop(context, false),
|
||||||
child: const Text('Cancel'),
|
child: const Text('Abbrechen'),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context, true),
|
onPressed: () => Navigator.pop(context, true),
|
||||||
child: const Text('Delete', style: TextStyle(color: Colors.red)),
|
child: const Text('Löschen', style: TextStyle(color: Colors.red)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -131,16 +141,23 @@ class TeamListItem extends StatelessWidget {
|
|||||||
|
|
||||||
if (confirmed == true && context.mounted) {
|
if (confirmed == true && context.mounted) {
|
||||||
try {
|
try {
|
||||||
await Provider.of<TeamProvider>(context, listen: false).deleteTeam(team.id);
|
await Provider.of<TeamProvider>(
|
||||||
|
context,
|
||||||
|
listen: false,
|
||||||
|
).deleteTeam(team.id);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(
|
||||||
const SnackBar(content: Text('Team deleted')),
|
context,
|
||||||
);
|
).showSnackBar(const SnackBar(content: Text('Team gelöscht')));
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text('Error: $e')),
|
SnackBar(
|
||||||
|
content: Text(
|
||||||
|
'Fehler: ${e.toString().replaceFirst('Exception: ', '')}',
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,21 +9,21 @@ class ThemeSelectorWidget extends StatelessWidget {
|
|||||||
final List<DropdownMenuItem<AppThemeOption>> dropdownElements = [
|
final List<DropdownMenuItem<AppThemeOption>> dropdownElements = [
|
||||||
const DropdownMenuItem(
|
const DropdownMenuItem(
|
||||||
value: AppThemeOption.lightBlue,
|
value: AppThemeOption.lightBlue,
|
||||||
child: Text("Light Blue"),
|
child: Text('Helles Blau'),
|
||||||
),
|
),
|
||||||
const DropdownMenuItem(
|
const DropdownMenuItem(
|
||||||
value: AppThemeOption.darkPurple,
|
value: AppThemeOption.darkPurple,
|
||||||
child: Text("Dark Purple"),
|
child: Text('Dunkles Lila'),
|
||||||
),
|
),
|
||||||
const DropdownMenuItem(
|
const DropdownMenuItem(
|
||||||
value: AppThemeOption.lightMint,
|
value: AppThemeOption.lightMint,
|
||||||
child: Text("Light Mint"),
|
child: Text('Helles Mint'),
|
||||||
),
|
),
|
||||||
const DropdownMenuItem(
|
const DropdownMenuItem(
|
||||||
value: AppThemeOption.darkAmber,
|
value: AppThemeOption.darkAmber,
|
||||||
child: Text("Dark Amber"),
|
child: Text('Dunkles Bernstein'),
|
||||||
),
|
),
|
||||||
const DropdownMenuItem(value: AppThemeOption.system, child: Text("System")),
|
const DropdownMenuItem(value: AppThemeOption.system, child: Text('System')),
|
||||||
];
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -39,7 +39,7 @@ class ThemeSelectorWidget extends StatelessWidget {
|
|||||||
child: Row(
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text("Theme"),
|
const Text('Design'),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
width: 250,
|
width: 250,
|
||||||
child: DropdownButtonFormField<AppThemeOption>(
|
child: DropdownButtonFormField<AppThemeOption>(
|
||||||
|
|||||||
@@ -45,11 +45,11 @@ static void my_application_activate(GApplication* application) {
|
|||||||
if (use_header_bar) {
|
if (use_header_bar) {
|
||||||
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
GtkHeaderBar* header_bar = GTK_HEADER_BAR(gtk_header_bar_new());
|
||||||
gtk_widget_show(GTK_WIDGET(header_bar));
|
gtk_widget_show(GTK_WIDGET(header_bar));
|
||||||
gtk_header_bar_set_title(header_bar, "frontend_splatournament_manager");
|
gtk_header_bar_set_title(header_bar, "Splatournament Manager");
|
||||||
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
gtk_header_bar_set_show_close_button(header_bar, TRUE);
|
||||||
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
gtk_window_set_titlebar(window, GTK_WIDGET(header_bar));
|
||||||
} else {
|
} else {
|
||||||
gtk_window_set_title(window, "frontend_splatournament_manager");
|
gtk_window_set_title(window, "Splatournament Manager");
|
||||||
}
|
}
|
||||||
|
|
||||||
gtk_window_set_default_size(window, 1280, 720);
|
gtk_window_set_default_size(window, 1280, 720);
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ dependencies:
|
|||||||
flutter_secure_storage: ^10.0.0
|
flutter_secure_storage: ^10.0.0
|
||||||
jwt_decoder: ^2.0.1
|
jwt_decoder: ^2.0.1
|
||||||
shared_preferences: ^2.3.3
|
shared_preferences: ^2.3.3
|
||||||
|
flutter_localizations:
|
||||||
|
sdk: flutter
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html lang="de">
|
||||||
<head>
|
<head>
|
||||||
<!--
|
<!--
|
||||||
If you are serving your web app in a path other than the root, change the
|
If you are serving your web app in a path other than the root, change the
|
||||||
@@ -18,18 +18,18 @@
|
|||||||
|
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
|
||||||
<meta name="description" content="A tournament Manager for Splatoon">
|
<meta name="description" content="Ein Turnier-Manager für Splatoon">
|
||||||
|
|
||||||
<!-- iOS meta tags & icons -->
|
<!-- iOS meta tags & icons -->
|
||||||
<meta name="mobile-web-app-capable" content="yes">
|
<meta name="mobile-web-app-capable" content="yes">
|
||||||
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
||||||
<meta name="apple-mobile-web-app-title" content="frontend_splatournament_manager">
|
<meta name="apple-mobile-web-app-title" content="Splatournament Manager">
|
||||||
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
<link rel="apple-touch-icon" href="icons/Icon-192.png">
|
||||||
|
|
||||||
<!-- Favicon -->
|
<!-- Favicon -->
|
||||||
<link rel="icon" type="image/png" href="favicon.png"/>
|
<link rel="icon" type="image/png" href="favicon.png"/>
|
||||||
|
|
||||||
<title>frontend_splatournament_manager</title>
|
<title>Splatournament Manager</title>
|
||||||
<link rel="manifest" href="manifest.json">
|
<link rel="manifest" href="manifest.json">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "frontend_splatournament_manager",
|
"name": "Splatournament Manager",
|
||||||
"short_name": "frontend_splatournament_manager",
|
"short_name": "Splatournament",
|
||||||
"start_url": ".",
|
"start_url": ".",
|
||||||
"display": "standalone",
|
"display": "standalone",
|
||||||
"background_color": "#0175C2",
|
"background_color": "#0175C2",
|
||||||
"theme_color": "#0175C2",
|
"theme_color": "#0175C2",
|
||||||
"description": "A tournament Manager for Splatoon",
|
"description": "Ein Turnier-Manager für Splatoon",
|
||||||
"orientation": "portrait-primary",
|
"orientation": "portrait-primary",
|
||||||
"prefer_related_applications": false,
|
"prefer_related_applications": false,
|
||||||
"icons": [
|
"icons": [
|
||||||
|
|||||||
@@ -90,12 +90,12 @@ BEGIN
|
|||||||
BLOCK "040904e4"
|
BLOCK "040904e4"
|
||||||
BEGIN
|
BEGIN
|
||||||
VALUE "CompanyName", "com.tikaiz" "\0"
|
VALUE "CompanyName", "com.tikaiz" "\0"
|
||||||
VALUE "FileDescription", "frontend_splatournament_manager" "\0"
|
VALUE "FileDescription", "Splatournament Manager" "\0"
|
||||||
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
VALUE "FileVersion", VERSION_AS_STRING "\0"
|
||||||
VALUE "InternalName", "frontend_splatournament_manager" "\0"
|
VALUE "InternalName", "frontend_splatournament_manager" "\0"
|
||||||
VALUE "LegalCopyright", "Copyright (C) 2026 com.tikaiz. All rights reserved." "\0"
|
VALUE "LegalCopyright", "Copyright (C) 2026 com.tikaiz. All rights reserved." "\0"
|
||||||
VALUE "OriginalFilename", "frontend_splatournament_manager.exe" "\0"
|
VALUE "OriginalFilename", "frontend_splatournament_manager.exe" "\0"
|
||||||
VALUE "ProductName", "frontend_splatournament_manager" "\0"
|
VALUE "ProductName", "Splatournament Manager" "\0"
|
||||||
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
VALUE "ProductVersion", VERSION_AS_STRING "\0"
|
||||||
END
|
END
|
||||||
END
|
END
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE instance, _In_opt_ HINSTANCE prev,
|
|||||||
FlutterWindow window(project);
|
FlutterWindow window(project);
|
||||||
Win32Window::Point origin(10, 10);
|
Win32Window::Point origin(10, 10);
|
||||||
Win32Window::Size size(1280, 720);
|
Win32Window::Size size(1280, 720);
|
||||||
if (!window.Create(L"frontend_splatournament_manager", origin, size)) {
|
if (!window.Create(L"Splatournament Manager", origin, size)) {
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
window.SetQuitOnClose(true);
|
window.SetQuitOnClose(true);
|
||||||
|
|||||||
Reference in New Issue
Block a user