diff --git a/README.md b/README.md index df7bdc0..328b716 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,14 @@
## 👨🏾‍💻 Project documentation. - Documentation +Learn all about the project through our documentation: Documentation + +
+ +## 👨🏾‍💻 Demo. +Want to see the project better? Access our demo: Demo + +
## 👨🏾‍💻 Techs @@ -108,7 +115,7 @@ This repository follows the semantic commit pattern, with the addition of the ta ### Guilds @@ -163,6 +170,17 @@ This repository follows the semantic commit pattern, with the addition of the ta
  • [x] Edit post
  • [x] Delete post
  • +
  • [x] Accounts
  • + +
  • [x] Players
  • + ## Show-Off diff --git a/backend/README.md b/backend/README.md index 1e08b6b..d3ec348 100644 --- a/backend/README.md +++ b/backend/README.md @@ -34,6 +34,8 @@ $ npm run start | GET | /news/find/:id | Find post | | POST | /news/edit | Edit post | +
    + ## 🕵🏾‍♂️ Routes Account | METHOD | ENDPOINT | DESCRIPTION | @@ -44,9 +46,21 @@ $ npm run start | PUT | /accounts/forgot-password | Update Password | | GET | /accounts/characters/:id | Get characters to account | | POST | /accounts/create-character | Create new character | -| GET | /accounts/change-character-name | Status system | -| POST | /accounts/change-character-name | Change character name | -| POST | /accounts/delete-character | Delete character | + +
    + +## 🕵🏾‍♂️ Routes Players + +| METHOD | ENDPOINT | DESCRIPTION | +| :----- | :------------------------- | :------------------------------------ | +| GET | /player/:name | Get Player Infos | +| GET | /player/:id/skills | Get Player Skills | +| GET | /player/:id/storage/:key | Get Player Storage | +| POST | /player/:id/deaths | Get Player Last 10 Deaths | +| GET | /player/:id/items | Get Player Items equipment | +| GET | /player/change-name | Status system | +| POST | /player/change-name | Change character name | +| POST | /player/delete | Delete character |
    @@ -62,10 +76,10 @@ $ npm run start ## 🕵🏾‍♂️ Routes Highscores -| METHOD | ENDPOINT | DESCRIPTION | -| :----- | :------------------------- | :------------------------------------ | -| GET | /highscores | Get Top 5 Players | -| POST | /highscores/:page/:limit | Ranking Players | +| METHOD | ENDPOINT | DESCRIPTION | +| :----- | :------------------------------- | :------------------------------------ | +| GET | /highscores | Get Top 5 Players | +| POST | /highscores/:page/:limit/:type | Ranking Players |
    @@ -85,18 +99,6 @@ $ npm run start
    -## 🕵🏾‍♂️ Routes Players - -| METHOD | ENDPOINT | DESCRIPTION | -| :----- | :------------------------- | :------------------------------------ | -| GET | /player/:name | Get Player Infos | -| GET | /player/:id/skills | Get Player Skills | -| GET | /player/:id/storage/:key | Get Player Storage | -| POST | /player/:id/deaths | Get Player Last 10 Deaths | -| GET | /player/:id/items | Get Player Items equipment | - -
    - ## 🕵🏾‍♂️ Routes Guilds | METHOD | ENDPOINT | DESCRIPTION | @@ -116,4 +118,24 @@ $ npm run start | GET | /dashboard/players | Get Total PLayers | | GET | /dashboard/guilds | Get Total Guilds | | GET | /dashboard/premium-points | Get accounts with the most premium points | -| GET | /dashboard/vocation | Get all vocations by id | \ No newline at end of file +| GET | /dashboard/vocation | Get all vocations by id | + +
    + +## 🕵🏾‍♂️ Routes Dashboard - Accounts + +| METHOD | ENDPOINT | DESCRIPTION | +| :----- | :------------------------- | :-----------------------------------------| +| GET | /dashboard/account/:name | Find account | +| POST | /dashboard/account | Update account | + +
    + +## 🕵🏾‍♂️ Routes Dashboard - Characters + +| METHOD | ENDPOINT | DESCRIPTION | +| :----- | :-------------------------------| :-----------------------------------------| +| GET | /dashboard/character/:name | Find character | +| GET | /dashboard/character-skills/:id | Find character | +| POST | /dashboard/character | Update character | +| POST | /dashboard/character-skills | Update characterSkills | \ No newline at end of file diff --git a/backend/app/Controllers/Account/Characters.ts b/backend/app/Controllers/Account/Characters.ts index 40abcf2..8837617 100644 --- a/backend/app/Controllers/Account/Characters.ts +++ b/backend/app/Controllers/Account/Characters.ts @@ -1,48 +1,47 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import { DeleteValidator, StoreValidator, UpdateValidator } from 'App/Validators/Account/Character' +import { StoreValidator } from 'App/Validators/Account/Character' import { Vocations } from 'Contracts/enums/Vocations' -import { Account } from 'App/Models' -import Database from '@ioc:Adonis/Lucid/Database' +import { Item, Player } from 'App/Models' import Env from '@ioc:Adonis/Core/Env' -import encrypt from 'js-sha1' + +import { + Character, + CharacterView, + CharacterRepository +} from 'App/Services' export default class CharactersAccount { - - private async getCharacters(account_id: number) { - return await Database - .from('players') - .select('players.id', 'players.level', 'players.name', 'players.vocation') - .where('players.account_id', account_id) - .orderBy('players.experience', 'desc'); - } + public character: Character = new Character(); + public characterView: CharacterView = new CharacterView(); + public characterRepository: CharacterRepository = new CharacterRepository(); - public async store({ request, response, auth }: HttpContextContract) { + public async store(ctx: HttpContextContract) { try { - const data = await request.validate(StoreValidator); + const data = await ctx.request.validate(StoreValidator); - const account = auth.user; + const account = ctx.auth.user; if (!account || !account.id) { - return response.unauthorized(); + return ctx.response.unauthorized(); } - const characters = await this.getCharacters(account.id); + const characters = await this.characterView.getByAccount(account.id); if (characters.length >= Env.get('CHARACTERS_PER_ACCOUNT')) { - return response.status(404).send({ message: 'You have too many characters on your account ' + characters.length + '/' + Env.get('CHARACTERS_PER_ACCOUNT')}); + return ctx.response.status(404).send({ message: 'You have too many characters on your account ' + characters.length + '/' + Env.get('CHARACTERS_PER_ACCOUNT')}); } const vocation = Vocations.find((vocation) => vocation.vocation_id === data.vocation); if (!vocation || !vocation.vocation_id) { - return response.status(404).send({ message: 'Vocation invalid'}); + return ctx.response.status(404).send({ message: 'Vocation invalid'}); } - const characterCopy = await Database.from('players').select('*').where('name', '=', vocation.name); + const characterCopy: Player[] = await this.characterView.findByName(vocation.name) as Player[]; if (!characterCopy.length) { console.log("Error find Sample Character: Edit file Vocations in contracts/enums/Vocations and set valid characters to copy names. Name Character to copy: " + vocation.name + " doesn\'t exist."); - return response.status(404).send({ message: "Wrong characters configuration. Try again or contact with admin."}); + return ctx.response.status(404).send({ message: "Wrong characters configuration. Try again or contact with admin."}); } const newPlayer = Object.assign(characterCopy[0], { @@ -59,149 +58,43 @@ export default class CharactersAccount { created: 0 }); - const result = await Database.table('players').returning('id').insert(newPlayer); + const result = await this.characterRepository.create(newPlayer); - const player = await Database.from('players').select('*').where('id', '=', result[0]); + const player: Player[] = await this.characterView.findById(result[0]) as Player[]; if (!player.length) { - return response.status(404).send({ message: "Error. Can't create character. Probably problem with database. Please try again later or contact with admin."}); + return ctx.response.status(404).send({ message: "Error. Can't create character. Probably problem with database. Please try again later or contact with admin."}); } for(let i = 0; i < 7; i++) { - const skillExists = await Database.from('player_skills').select('skillid').where('player_id', '=', player[0].id).andWhere('skillid', '=', i); + const skillExists = await this.characterView.checkSkillId(player[0].id, i); if (!skillExists.length) { - await Database.table('player_skills').insert({ - player_id: player[0].id, - skillid: i, - value: 10, - count: 0 - }) + await this.character.insertSkill(player[0].id, i); } } - const items_to_copy = await Database.from('player_items').select('*').where('player_id', '=', characterCopy[0].id); + const items_to_copy: Item[] = await this.characterView.getItems(characterCopy[0].id) as Item[]; for(let item of items_to_copy) { - await Database.table('player_skills').insert({ - player_id: player[0].id, - pid: item.pid, - sid: item.sid, - itemtype: item.itemtype, - count: item.count, - attributes: item.attributes - }) + await this.character.insertItems(player[0].id, item.pid, item.sid, item.itemtype, item.count, item.attributes); }; - return response.status(200).send({ status: 200, message: 'Character created successfully!'}); + return ctx.response.status(200).send({ status: 200, message: 'Character created successfully!'}); } catch (err) { console.log('Error getPlayersAccount Query: ', err); - return response.badRequest(err.messages); + return ctx.response.badRequest(err.messages); } } - public async show({ request, response }: HttpContextContract) { + public async show(ctx: HttpContextContract) { try { - const characters = await this.getCharacters(request.param('id')); + const characters = await this.characterView.getByAccount(ctx.request.param('id')); - return response.status(200).send({ result: characters}); + return ctx.response.status(200).send({ result: characters}); } catch(err) { console.log('Error getPlayersAccount Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) - } - } - - public async update({ request, response, auth }: HttpContextContract) { - try { - if (!Env.get('CHANGE_NAME')) { - return response.status(404).send({ message: 'Change character name is disabled.' }); - } - - const data = await request.validate(UpdateValidator); - - const account = auth.user; - - if (!account || !account.id) { - return response.unauthorized(); - } - - if (account.premium_points < Env.get('POINTS_TO_CHANGE_NAME')) { - return response.status(404).send({ message: "You don't have the points needed to change the name. It is necessary: " + Env.get('POINTS_TO_CHANGE_NAME') + " points." }); - } - - const character = await Database.from('players').select('name', 'online').where('id', '=', data.character_id).andWhere('account_id', '=', account.id); - - if (!character.length) - { - return response.status(404).send({ message: 'The character does not belong to your account.' }); - } - - if (character[0].online === 1) - { - return response.status(404).send({ message: 'The character cannot be online.' }); - } - - const updateCharacter = await Database.from('players').where('id', '=', data.character_id).update({ name: data.new_name }); - - await Database.from('accounts').where('id', '=', account.id).update({ premium_points: account.premium_points - Env.get('POINTS_TO_CHANGE_NAME')}); - - if (!updateCharacter) { - return response.status(404).send({ message: "Error. Can't change character name. Probably problem with database. Please try again later or contact with admin." }); - } - - return response.status(200).send({ status: 200, message: "The character " + character[0].name + " name has been changed to " + data.new_name + "." }); - } catch(err) { - console.log('Error Change Character Name Query: ', err); - return response.badRequest(err.messages); - } - } - - public async destroy({ request, response, auth }: HttpContextContract) { - try { - const data = await request.validate(DeleteValidator); - - const account = auth.user; - - if (!account || !account.id) - return response.unauthorized(); - - const verifyPassword = await Account - .query() - .where('name', account.name) - .where('password', encrypt(data.password)) - .firstOrFail(); - - if (!verifyPassword) - return response.status(404).send({ message: 'Wrong password.' }); - - const character = await Database - .from('players') - .select('name', 'deleted', 'online') - .where('id', '=', data.character_id) - .andWhere('account_id', '=', account.id); - - if (!character.length) - return response.status(404).send({ message: 'The character does not belong to your account.' }); - - if (character[0].online === 1) - return response.status(404).send({ message: 'You cannot delete a character that is online.' }); - - if (character[0].deleted === 1) - return response.status(404).send({ message: 'This character is already deleted.' }); - - const house = await Database.from('houses').select('id').where('owner', '=', data.character_id); - - if (house.length) - return response.status(404).send({ message: 'You cannot delete a character that has a house.' }); - - const updateCharacter = await Database.from('players').where('id', '=', data.character_id).update({ deleted: 1 }); - - if (!updateCharacter) - return response.status(404).send({ message: "Error. Unable to delete character. Probably problem with database. Please try again later or contact with admin." }); - - return response.status(200).send({ status: 200, message: "The character " + character[0].name + " has been deleted." }); - } catch (err) { - + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) } } } diff --git a/backend/app/Controllers/Account/ForgotPassword.ts b/backend/app/Controllers/Account/ForgotPassword.ts index c446f86..b413a57 100644 --- a/backend/app/Controllers/Account/ForgotPassword.ts +++ b/backend/app/Controllers/Account/ForgotPassword.ts @@ -5,8 +5,8 @@ import Mail from '@ioc:Adonis/Addons/Mail' import faker from 'faker' export default class UserForgotPasswordController { - public async store({ request }: HttpContextContract) { - const { email, redirectUrl } = await request.validate(StoreValidator) + public async store(ctx: HttpContextContract) { + const { email, redirectUrl } = await ctx.request.validate(StoreValidator) const account = await Account.findByOrFail('email', email) @@ -24,12 +24,12 @@ export default class UserForgotPasswordController { }) } - public async show({ params }: HttpContextContract) { - await AccountKey.findByOrFail('key', params.key) + public async show(ctx: HttpContextContract) { + await AccountKey.findByOrFail('key', ctx.params.key) } - public async update({ request }: HttpContextContract) { - const { key, password } = await request.validate(UpdateValidator) + public async update(ctx: HttpContextContract) { + const { key, password } = await ctx.request.validate(UpdateValidator) const accountKey = await AccountKey.findByOrFail('key', key) diff --git a/backend/app/Controllers/Account/Main.ts b/backend/app/Controllers/Account/Main.ts index b4e000c..69d2f34 100644 --- a/backend/app/Controllers/Account/Main.ts +++ b/backend/app/Controllers/Account/Main.ts @@ -1,8 +1,8 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' export default class AccountController { - public async show({ auth }: HttpContextContract) { - const account = auth.user!; + public async show(ctx: HttpContextContract) { + const account = ctx.auth.user!; /** * @TODO => Filtrar somente os dados que devem ser retornados a fins de consumo no frontend */ diff --git a/backend/app/Controllers/Account/Register.ts b/backend/app/Controllers/Account/Register.ts index 4dce9a5..d136f16 100644 --- a/backend/app/Controllers/Account/Register.ts +++ b/backend/app/Controllers/Account/Register.ts @@ -5,8 +5,8 @@ import faker from 'faker' import Mail from '@ioc:Adonis/Addons/Mail' export default class AccountRegisterController { - public async store({ request, response }: HttpContextContract) { - const { email, name, password } = await request.validate(StoreValidator); + public async store(ctx: HttpContextContract) { + const { email, name, password } = await ctx.request.validate(StoreValidator); const account = await Account.create({ email, @@ -55,11 +55,11 @@ export default class AccountRegisterController { message.htmlView('mails/register') }) - return response.send({ status: 200, message: 'Created Successfully'}); + return ctx.response.send({ status: 200, message: 'Created Successfully'}); } - public async show({ params }: HttpContextContract) { - const accountKey = await AccountKey.findByOrFail('key', params.code); + public async show(ctx: HttpContextContract) { + const accountKey = await AccountKey.findByOrFail('key', ctx.params.code); const account = await accountKey.related('account').query().firstOrFail() return account; diff --git a/backend/app/Controllers/Auth/Main.ts b/backend/app/Controllers/Auth/Main.ts index df19d43..decaad9 100644 --- a/backend/app/Controllers/Auth/Main.ts +++ b/backend/app/Controllers/Auth/Main.ts @@ -4,8 +4,8 @@ import { Account } from 'App/Models' import encrypt from 'js-sha1'; export default class AuthController { - public async store({ request, auth }: HttpContextContract) { - const { name, password, rememberMe } = await request.validate(StoreValidator); + public async store(ctx: HttpContextContract) { + const { name, password, rememberMe } = await ctx.request.validate(StoreValidator); const encryptedPassword = encrypt(password); @@ -18,7 +18,7 @@ export default class AuthController { if (!user) return ""; - const token = await auth.use('api').generate(user, { + const token = await ctx.auth.use('api').generate(user, { expiresIn: rememberMe ? '7 days' : '30mins' }); diff --git a/backend/app/Controllers/Dashboard/Accounts.ts b/backend/app/Controllers/Dashboard/Accounts.ts index b4ca8f7..4a36c0a 100644 --- a/backend/app/Controllers/Dashboard/Accounts.ts +++ b/backend/app/Controllers/Dashboard/Accounts.ts @@ -1,25 +1,72 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { UpdateValidator } from 'App/Validators/Dashboard/Accounts' +import { + Account, + AccountView, + AccountRepository, + CharacterView +} from 'App/Services' +import { Account as AccountModel } from 'App/Models'; export default class AccountsController { - public async show({ response, bouncer }: HttpContextContract) { + public account: Account = new Account(); + public accountRepository: AccountRepository = new AccountRepository(); + public accountView: AccountView = new AccountView(); + public characterView: CharacterView = new CharacterView(); + + public async index(ctx: HttpContextContract) { try { - await bouncer.with('DashboardPolicy').authorize('viewList'); + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); - const accounts = await Database - .from('accounts') - .count('* as total'); + const accounts = await this.accountView.getTotalAccounts(); - return response.status(200).send({ result: accounts}); + return ctx.response.status(200).send({ result: accounts}); } catch(err) { console.log('Error getTotalAccounts Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) + return ctx.response.status(400).send({ status: 200, message: 'An error occurred, check the api console.'}) } } - public async edit({}: HttpContextContract) {} + public async show(ctx: HttpContextContract) { + try { + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); + + const account = await this.accountView.getAccountByName(ctx.request.param('name')) as AccountModel[]; + + if (!account.length) { + return ctx.response.status(404).send({ message: "Account not found!"}); + } + + const characters = await this.characterView.getByAccount(account[0].id); - public async update({}: HttpContextContract) {} + return ctx.response.status(200).send({ status: 200, result: { account, characters }}); + } catch(err) { + console.log('Error findAccount Query: ', err); + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) + } + } - public async destroy({}: HttpContextContract) {} + public async update(ctx: HttpContextContract) { + try { + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); + const data = await ctx.request.validate(UpdateValidator); + + const account = await this.account.validateName(data.id, data.name); + + if (account.length) { + return ctx.response.status(404).send({ message: "Error. The username is already used."}); + } + + const affectedRows = await this.accountRepository.update(data.id, data); + + if (!affectedRows) { + return ctx.response.status(404).send({ message: "Account not found."}); + } + + return ctx.response.status(200).send({ status: 200, message: "Account successfully updated." }); + } catch (err) { + console.log('Error updateAccount Query: ', err); + return ctx.response.status(400).send({ message: err}) + } + } } diff --git a/backend/app/Controllers/Dashboard/Dashboard.ts b/backend/app/Controllers/Dashboard/Dashboard.ts deleted file mode 100644 index e69de29..0000000 diff --git a/backend/app/Controllers/Dashboard/Guilds.ts b/backend/app/Controllers/Dashboard/Guilds.ts index 3001c66..137ab60 100644 --- a/backend/app/Controllers/Dashboard/Guilds.ts +++ b/backend/app/Controllers/Dashboard/Guilds.ts @@ -1,25 +1,19 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { GuildView } from 'App/Services'; export default class GuildsController { - public async show({ response, bouncer }: HttpContextContract) { + public guildView: GuildView = new GuildView(); + + public async show(ctx: HttpContextContract) { try { - await bouncer.with('DashboardPolicy').authorize('viewList'); + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); - const accounts = await Database - .from('guilds') - .count('* as total'); + const accounts = await this.guildView.getTotalGuilds(); - return response.status(200).send({ result: accounts}); + return ctx.response.status(200).send({ result: accounts}); } catch(err) { console.log('Error getTotalGuilds Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) } } - - public async edit({}: HttpContextContract) {} - - public async update({}: HttpContextContract) {} - - public async destroy({}: HttpContextContract) {} } diff --git a/backend/app/Controllers/Dashboard/News.ts b/backend/app/Controllers/Dashboard/News.ts index 8c612d0..58983ae 100644 --- a/backend/app/Controllers/Dashboard/News.ts +++ b/backend/app/Controllers/Dashboard/News.ts @@ -1,33 +1,32 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' import { StoreValidator, UpdateValidator } from 'App/Validators/News' -import Database from '@ioc:Adonis/Lucid/Database' +import { NewsRepository, NewsView } from 'App/Services'; export default class AccountsController { - public async index({ request, response }: HttpContextContract) { + public newsView: NewsView = new NewsView(); + public newsRepository: NewsRepository = new NewsRepository(); + + public async index(ctx: HttpContextContract) { try { - const news = await Database - .from('electro_news') - .select('id', 'title', 'body', 'created_at') - .orderBy('created_at', 'desc') - .paginate(request.param('page', 1), request.param('limit')); + const news = await this.newsView.getNews(ctx.request.param('page'), ctx.request.param('limit')); - return response.status(200).send({ status: 200, news }); + return ctx.response.status(200).send({ status: 200, news }); } catch(err) { console.log('Error getNews Query: ', err); - return response.status(400).send({ error: 'An error occurred, check the api console.'}); + return ctx.response.status(400).send({ error: 'An error occurred, check the api console.'}); } } - public async store({ request, response, auth, bouncer }: HttpContextContract) { + public async store(ctx: HttpContextContract) { try { - await bouncer.with('DashboardPolicy').authorize('viewList'); + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); - const data = await request.validate(StoreValidator); + const data = await ctx.request.validate(StoreValidator); - const account = auth.user; + const account = ctx.auth.user; if (!account || !account.id) { - return response.unauthorized(); + return ctx.response.unauthorized(); } const news = { @@ -39,52 +38,38 @@ export default class AccountsController { created_at: new Date() } - await Database.table('electro_news').returning('id').insert(news); + await this.newsRepository.create(news); - return response.status(200).send({ status: 200, message: 'New Post created successfully!'}); + return ctx.response.status(200).send({ status: 200, message: 'New Post created successfully!'}); } catch (err) { console.log('Error createNewPage Query: ', err); - return response.badRequest(err.messages); + return ctx.response.badRequest(err.messages); } } - public async show({ request, response, bouncer }: HttpContextContract) { - await bouncer.with('DashboardPolicy').authorize('viewList'); + public async show(ctx: HttpContextContract) { + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); - const page = await Database - .from('electro_news') - .select('*') - .where('id', '=', request.param('id')) + const page = await this.newsView.findNewsById(ctx.request.param('id')); if (!page.length) { - return response.status(404).send({ message: 'News not found.' }); + return ctx.response.status(404).send({ message: 'News not found.' }); } - return response.status(200).send({ status: 200, page }); + return ctx.response.status(200).send({ status: 200, page }); } - public async edit({}: HttpContextContract) {} - - public async update({ request, response, auth, bouncer }: HttpContextContract) { - await bouncer.with('DashboardPolicy').authorize('viewList'); + public async update(ctx: HttpContextContract) { + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); - const data = await request.validate(UpdateValidator); + const data = await ctx.request.validate(UpdateValidator); - const account = auth.user; + const account = ctx.auth.user; if (!account || !account.id) { - return response.unauthorized(); + return ctx.response.unauthorized(); } - await Database.from('electro_news') - .where('id', '=', data.news_id) - .update({ - title: data.title, - body: data.description, - hidden: data.hidden ? 1 : 0, - updated_at: new Date() - }); + await this.newsRepository.update(data.news_id, data); - return response.status(200).send({ status: 200, message: "Post successfully updated." }); + return ctx.response.status(200).send({ status: 200, message: "Post successfully updated." }); } - - public async destroy({}: HttpContextContract) {} } diff --git a/backend/app/Controllers/Dashboard/PlayerSkills.ts b/backend/app/Controllers/Dashboard/PlayerSkills.ts new file mode 100644 index 0000000..fd39534 --- /dev/null +++ b/backend/app/Controllers/Dashboard/PlayerSkills.ts @@ -0,0 +1,42 @@ +import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; +import { UpdateValidator } from 'App/Validators/Dashboard/CharacterSkills'; +import { Skill, SkillView } from 'App/Services'; + +export default class PlayersController { + public skill: Skill = new Skill(); + public skillView: SkillView = new SkillView(); + + public async show(ctx: HttpContextContract) { + try { + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); + + const skills = await this.skillView.getCharacterSkills(ctx.request.param('id')); + + if (!skills.length) { + return ctx.response.status(404).send({ message: "Character not found!" }); + } + + return ctx.response.status(200).send({ status: 200, result: skills }); + } catch(err) { + console.log('Error findCharacterSkills: ', err); + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) + } + } + + public async update(ctx: HttpContextContract) { + try { + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); + + const data = await ctx.request.validate(UpdateValidator); + + for(let i = 0; i < 7; i++) { + await this.skill.updateCharacterSkill(data.id, data.skills[i]); + } + + return ctx.response.status(200).send({ status: 200, message: "Skills successfully updated." }); + } catch (err) { + console.log('Error updateCharacterSkills: ', err); + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) + } + } +} diff --git a/backend/app/Controllers/Dashboard/Players.ts b/backend/app/Controllers/Dashboard/Players.ts index 6ff46cc..acad7fd 100644 --- a/backend/app/Controllers/Dashboard/Players.ts +++ b/backend/app/Controllers/Dashboard/Players.ts @@ -1,25 +1,59 @@ -import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'; +import { UpdateValidator } from 'App/Validators/Dashboard/Characters'; +import { CharacterView, CharacterRepository } from 'App/Services'; export default class PlayersController { - public async show({ response, bouncer }: HttpContextContract) { + public characterView: CharacterView = new CharacterView(); + public characterRepository: CharacterRepository = new CharacterRepository(); + + public async index(ctx: HttpContextContract) { try { - await bouncer.with('DashboardPolicy').authorize('viewList'); + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); - const accounts = await Database - .from('players') - .count('* as total'); + const accounts = await this.characterView.getTotalCharacters(); - return response.status(200).send({ result: accounts}); - } catch(err) { + return ctx.response.status(200).send({ result: accounts }); + } + catch(err) { console.log('Error getTotalPlayers Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) + } + } + + public async show(ctx: HttpContextContract) { + try { + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); + + const character = await this.characterView.findByName(ctx.request.param('name')); + + if (!character.length) { + return ctx.response.status(404).send({ message: "Character not found!" }); + } + + return ctx.response.status(200).send({ status: 200, result: character[0] }); + } + catch(err) { + console.log('Error findCharacter Query: ', err); + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) } } - public async edit({}: HttpContextContract) {} + public async update(ctx: HttpContextContract) { + try { + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); - public async update({}: HttpContextContract) {} + const data = await ctx.request.validate(UpdateValidator); + + const character = await this.characterRepository.update(data); + + if (character !== "Character successfully updated.") + return ctx.response.status(404).send({ message: character }); - public async destroy({}: HttpContextContract) {} + return ctx.response.status(200).send({ status: 200, message: character }); + } + catch (err) { + console.log('Error updateAccount Query: ', err); + return ctx.response.status(400).send({ message: err}) + } + } } diff --git a/backend/app/Controllers/Dashboard/PremiumPoints.ts b/backend/app/Controllers/Dashboard/PremiumPoints.ts index ac58701..0803c42 100644 --- a/backend/app/Controllers/Dashboard/PremiumPoints.ts +++ b/backend/app/Controllers/Dashboard/PremiumPoints.ts @@ -1,27 +1,19 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { AccountView } from 'App/Services'; export default class PremiumPointsController { - public async show({ response, bouncer }: HttpContextContract) { + public accountView: AccountView = new AccountView(); + + public async show(ctx: HttpContextContract) { try { - await bouncer.with('DashboardPolicy').authorize('viewList'); + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); - const accounts = await Database - .from('accounts') - .select('premium_points', 'name') - .orderBy('premium_points', 'desc') - .limit(10); + const accounts = await this.accountView.getTopPremiumPoints(); - return response.status(200).send({ result: accounts}); + return ctx.response.status(200).send({ result: accounts}); } catch(err) { console.log('Error getTopPremiumPoints Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) } } - - public async edit({}: HttpContextContract) {} - - public async update({}: HttpContextContract) {} - - public async destroy({}: HttpContextContract) {} } diff --git a/backend/app/Controllers/Dashboard/Vocations.ts b/backend/app/Controllers/Dashboard/Vocations.ts index e9fb638..26da3d1 100644 --- a/backend/app/Controllers/Dashboard/Vocations.ts +++ b/backend/app/Controllers/Dashboard/Vocations.ts @@ -1,27 +1,19 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { CharacterView } from 'App/Services'; export default class PremiumPointsController { - public async show({ response, bouncer }: HttpContextContract) { + public characterView: CharacterView = new CharacterView(); + + public async show(ctx: HttpContextContract) { try { - await bouncer.with('DashboardPolicy').authorize('viewList'); + await ctx.bouncer.with('DashboardPolicy').authorize('viewList'); - const vocations = await Database - .from('players') - .select('vocation') - .count('* as total') - .groupBy('vocation'); + const vocations = await this.characterView.getTotalVocations(); - return response.status(200).send({ result: vocations}); + return ctx.response.status(200).send({ result: vocations}); } catch(err) { console.log('Error getTopPremiumPoints Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) } } - - public async edit({}: HttpContextContract) {} - - public async update({}: HttpContextContract) {} - - public async destroy({}: HttpContextContract) {} } diff --git a/backend/app/Controllers/Guilds/Main.ts b/backend/app/Controllers/Guilds/Main.ts index 2108ae3..3c510c6 100644 --- a/backend/app/Controllers/Guilds/Main.ts +++ b/backend/app/Controllers/Guilds/Main.ts @@ -1,46 +1,58 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' import { StoreValidator } from 'App/Validators/Guilds/Register' -import Database from '@ioc:Adonis/Lucid/Database' - +import { + Character, + CharacterView, + GuildRepository, + GuildView +} from 'App/Services' +import { Player } from 'App/Models'; + +interface Guild { + id: number, + rank_id: number +} export default class GuildsController { - public async index({ request, response }: HttpContextContract) { + public character: Character = new Character(); + public characterView: CharacterView = new CharacterView(); + public guildRepository: GuildRepository = new GuildRepository(); + public guildView: GuildView = new GuildView(); + + public async index(ctx: HttpContextContract) { try { - const guilds = await Database - .from('guilds') - .select('id', 'name', 'motd', 'logo_name', 'description') - .paginate(request.param('page', 1), request.param('limit')); + const guilds = await this.guildView.getGuilds(ctx.request.param('page'), ctx.request.param('limit')); - return response.status(200).send({ status: 200, result: guilds }); + return ctx.response.status(200).send({ status: 200, result: guilds }); } catch(err) { - console.log('Error getGuilds Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) + console.log('Error getGuilds: ', err); + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) } } - public async create({ request, response, auth }: HttpContextContract) { - const data = await request.validate(StoreValidator); + public async create(ctx: HttpContextContract) { + const data = await ctx.request.validate(StoreValidator); - const account = auth.user; + const account = ctx.auth.user; if (!account || !account.id) { - return response.unauthorized(); + return ctx.response.unauthorized(); } - const character = await Database.from('players').select('name', 'online', 'rank_id').where('id', '=', data.character_id).andWhere('account_id', '=', account.id); + const character = await this.characterView.findByIdAndAccount(data.character_id, account.id) as Player[]; if (!character.length) { - return response.status(404).send({ message: 'The character does not belong to your account.' }); + return ctx.response.status(404).send({ message: 'The character does not belong to your account.' }); } if (character[0].online === 1) { - return response.status(404).send({ message: 'The character cannot be online.' }); + return ctx.response.status(404).send({ message: 'The character cannot be online.' }); } if (character[0].rank_id !== 0) { - return response.status(404).send({ message: 'Your character already has a guild.' }); + return ctx.response.status(404).send({ message: 'Your character already has a guild.' }); } const newGuild = { @@ -58,68 +70,30 @@ export default class GuildsController { description: 'New guild. Leader must edit this text' }; - const result = await Database.table('guilds').returning('id').insert(newGuild); + const result = await this.guildRepository.create(newGuild); - const guild = await Database.from('guilds').innerJoin('guild_ranks', 'guild_ranks.guild_id', 'guilds.id').select('guild_ranks.id as rank_id').where('guilds.id', '=', result[0]).andWhere('guild_ranks.level', '=', 3); + const guild = await this.guildView.getGuildById(result[0]) as Guild[]; if (!guild.length) { - return response.status(404).send({ message: "Error. Can't create guild. Probably problem with database. Please try again later or contact with admin."}); + return ctx.response.status(404).send({ message: "Error. Can't create guild. Probably problem with database. Please try again later or contact with admin."}); } + + await this.character.updateRankId(data.character_id, guild[0].rank_id); - await Database.from('players').where('id', '=', data.character_id).update({ rank_id: guild[0].rank_id }); - - return response.status(200).send({ status: 200, message: 'Guild created successfully!'}); + return ctx.response.status(200).send({ status: 200, message: 'Guild created successfully!'}); } - public async show({ request, response }: HttpContextContract) { + public async show(ctx: HttpContextContract) { try { - let name = request.param('name'); - - name = await name - .replace(/%20/g, " ") - .replace(/'+'/g, " ") - .replace(/'/g, "") - .replace(/%27/g, "") - .replace(/-/g, "") - .replace(/"/g, "") - .replace(/%22/g, ""); - - const guild = await Database - .from('guilds') - .innerJoin('players', 'players.id', 'guilds.ownerid') - .select( - 'guilds.id', - 'guilds.name', - 'guilds.description', - 'guilds.ownerid as owner_id', - 'guilds.creationdata as creation_data', - 'players.name as owner_name', - ) - .where('guilds.name', '=', name); + const guild = await this.guildView.getGuildByName(ctx.request.param('name')) as Guild[]; if (!guild.length) { - return response.status(404).send({ message: "Guild not found." }); + return ctx.response.status(404).send({ message: "Guild not found." }); } - const guildRanks = await Database - .from('guild_ranks') - .select('id') - .where('guild_id', '=', guild[0].id); - - const memberList = await Database.from('guilds') - .innerJoin('guild_ranks', 'guild_ranks.guild_id', '=', 'guilds.id') - .innerJoin('players', 'players.rank_id', 'guild_ranks.id') - .select( - 'guild_ranks.level', - 'guild_ranks.name as rank_name', - 'players.id', - 'players.name', - 'players.vocation', - 'players.level as player_level', - 'players.online' - ) - .where('guilds.id', '=', guild[0].id) - .orderBy('guild_ranks.level', 'desc'); + const guildRanks = await this.guildView.getGuildRanks(guild[0].id); + + const memberList = await this.guildView.getGuildMembers(guild[0].id); const result = { info: guild[0], @@ -127,16 +101,10 @@ export default class GuildsController { guild_members: memberList } - return response.status(200).send({ status: 200, result }); + return ctx.response.status(200).send({ status: 200, result }); } catch(err) { console.log('Error getGuild Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) } } - - public async edit({}: HttpContextContract) {} - - public async update({}: HttpContextContract) {} - - public async destroy({}: HttpContextContract) {} } diff --git a/backend/app/Controllers/Guilds/PlayersWithGuild.ts b/backend/app/Controllers/Guilds/PlayersWithGuild.ts index e1f385f..16fe23f 100644 --- a/backend/app/Controllers/Guilds/PlayersWithGuild.ts +++ b/backend/app/Controllers/Guilds/PlayersWithGuild.ts @@ -1,25 +1,23 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { GuildView } from 'App/Services' export default class PlayersWithGuildController { - public async show({ response, auth }: HttpContextContract) { + public guildView: GuildView = new GuildView(); + + public async show(ctx: HttpContextContract) { try { - const account = auth.user; + const account = ctx.auth.user; if (!account || !account.id) { - return response.unauthorized(); + return ctx.response.unauthorized(); } - const character = await Database - .from('players') - .select('id', 'name') - .where('account_id', '=', account.id) - .andWhere('rank_id', '=', 0); + const character = await this.guildView.getCharactersWithGuild(account.id); - return response.status(200).send({ status: 200, character }); + return ctx.response.status(200).send({ status: 200, character }); } catch(err) { console.log('Error getPlayersWithGuild Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) } } } diff --git a/backend/app/Controllers/Highscores/Main.ts b/backend/app/Controllers/Highscores/Main.ts index faacb7b..28b92d9 100644 --- a/backend/app/Controllers/Highscores/Main.ts +++ b/backend/app/Controllers/Highscores/Main.ts @@ -1,33 +1,28 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { HighscoresService } from 'App/Services' export default class HighscoresController { - public async show({ response }: HttpContextContract) { + public highscoresService: HighscoresService = new HighscoresService(); + + public async show(ctx: HttpContextContract) { try { - const topRank = await Database - .from('players') - .select('id', 'name', 'level', 'vocation', 'experience', 'online') - .orderBy('experience', 'desc') - .limit(5); - return response.status(200).send({ result: topRank}); + const topRank = await this.highscoresService.topRankPlayers(); + + return ctx.response.status(200).send({ result: topRank }); } catch(err) { - console.log('Error getTop5Players Query: ', err); - return response.status(400).send({ error: 'An error occurred, check the api console.'}); + console.log('Error getTop5Players: ', err); + return ctx.response.status(400).send({ error: 'An error occurred, check the api console.'}); } } - public async getRank({ request, response }: HttpContextContract) { + public async getRank(ctx: HttpContextContract) { try { - const rank = await Database - .from('players') - .select('name', 'vocation', 'level', 'experience', 'online') - .orderBy('experience', 'desc') - .paginate(request.param('page', 1), request.param('limit')); + const rank = await this.highscoresService.find(ctx.request.param('page'), ctx.request.param('limit'), ctx.request.param('type').replace(/%20/g, " ")); - return response.status(200).send({ status: 200, result: rank}); + return ctx.response.status(200).send({ status: 200, result: rank}); } catch (err) { - console.log('Error getRanking Query: ', err); - return response.status(404).send({ error: 'An error ocurred, check the api console.' }); + console.log('Error getRanking: ', err); + return ctx.response.status(404).send({ error: 'An error ocurred, check the api console.' }); } } } diff --git a/backend/app/Controllers/Lastkills/Main.ts b/backend/app/Controllers/Lastkills/Main.ts index 926bf50..2c4f658 100644 --- a/backend/app/Controllers/Lastkills/Main.ts +++ b/backend/app/Controllers/Lastkills/Main.ts @@ -1,24 +1,26 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { DeathService } from 'App/Services' +interface Death { + player_name: String, + monster_name: String, + player_exists: Number +} export default class LastKillsController { - public async show({ request, response }: HttpContextContract) { + public deathService: DeathService = new DeathService(); + + public async show(ctx: HttpContextContract) { try { - const { remote_url } = request.body(); + const { remote_url } = ctx.request.body(); let players_deaths_count = 0; const last_kills: Object[] = []; - const playersDeath = await Database - .from('player_deaths') - .innerJoin('players', 'players.id', 'player_deaths.player_id') - .select('player_deaths.id', 'player_deaths.date', 'player_deaths.level', 'players.name') - .orderBy('player_deaths.date', 'desc') - .paginate(request.param('page', 1), request.param('limit')); + const playersDeath: any = await this.deathService.getLastKills(ctx.request.param('page'), ctx.request.param('limit')); if (!playersDeath.length) { - return response.status(404).send({ message: 'There are no recorded deaths.' }); + return ctx.response.status(404).send({ message: 'There are no recorded deaths.' }); } for(let death of playersDeath) { @@ -28,14 +30,7 @@ export default class LastKillsController { let killers_string = '' + death.name + ' '; - const killers = await Database - .from('killers') - .leftJoin('environment_killers', 'environment_killers.kill_id', 'killers.id') - .leftJoin('player_killers', 'player_killers.kill_id', 'killers.id') - .leftJoin('players', 'players.id', 'player_killers.player_id') - .select('environment_killers.name AS monster_name', 'players.name AS player_name', 'players.deleted AS player_exists') - .where('killers.death_id', '=', death.id) - .orderBy('killers.final_hit', 'desc'); + const killers: Death[] = await this.deathService.getKillers(death.id) as Death[]; let i = 0; let count = killers.length; @@ -91,10 +86,11 @@ export default class LastKillsController { world_id: 0 }) } - return response.status(200).send({ status: 200, total: playersDeath.lastPage, last_kills }); + + return ctx.response.status(200).send({ status: 200, total: playersDeath.lastPage, last_kills }); } catch(err) { console.log('Error getPlayersDeaths Query: ', err); - return response.status(400).send({ error: 'An error occurred, check the api console.'}); + return ctx.response.status(400).send({ error: 'An error occurred, check the api console.'}); } } } diff --git a/backend/app/Controllers/News/Main.ts b/backend/app/Controllers/News/Main.ts index 02a53ba..e43db4c 100644 --- a/backend/app/Controllers/News/Main.ts +++ b/backend/app/Controllers/News/Main.ts @@ -1,20 +1,17 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { NewsView } from 'App/Services' export default class NewsController { - public async show({ request, response }: HttpContextContract) { + public newsView: NewsView = new NewsView(); + + public async show(ctx: HttpContextContract) { try { - const news = await Database - .from('electro_news') - .select('id', 'title', 'body', 'created_at') - .where('hidden', '=', 0) - .orderBy('created_at', 'desc') - .paginate(request.param('page', 1), request.param('limit')); + const news = await this.newsView.getNews(ctx.request.param('page'), ctx.request.param('limit')); - return response.status(200).send({ status: 200, news }); + return ctx.response.status(200).send({ status: 200, news }); } catch(err) { console.log('Error getNews Query: ', err); - return response.status(400).send({ error: 'An error occurred, check the api console.'}); + return ctx.response.status(400).send({ error: 'An error occurred, check the api console.'}); } } } diff --git a/backend/app/Controllers/Online/Main.ts b/backend/app/Controllers/Online/Main.ts index 591bb1e..9bc2ba8 100644 --- a/backend/app/Controllers/Online/Main.ts +++ b/backend/app/Controllers/Online/Main.ts @@ -1,27 +1,24 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { OnlineService } from 'App/Services' export default class OnlineController { - public async show({ response }: HttpContextContract) { + public onlineService: OnlineService = new OnlineService(); + + public async show(ctx: HttpContextContract) { try { - const playersOnline = await Database - .from('players') - .innerJoin('accounts', 'accounts.id', 'players.account_id') - .select('accounts.country', 'players.skull', 'players.skulltime', 'players.name', 'players.level', 'players.vocation') - .where('players.online', '>', '0') - .orderBy('experience', 'desc'); + const playersOnline = await this.onlineService.getPlayersOnline(); - const serverRecord = await Database.from('server_record').select('record', 'timestamp').where('world_id', '=', 0).orderBy('record', 'desc').limit(1) + const serverRecord = await this.onlineService.getRecord(0); const result = { serverRecord, playersOnline }; - return response.status(200).send({ status: 200, result}); + return ctx.response.status(200).send({ status: 200, result}); } catch(err) { console.log('Error getPlayersOnline Query: ', err); - return response.status(400).send({ error: 'An error occurred, check the api console.'}); + return ctx.response.status(400).send({ error: 'An error occurred, check the api console.'}); } } } diff --git a/backend/app/Controllers/Players/Deaths.ts b/backend/app/Controllers/Players/Deaths.ts index c9dabfc..82ea767 100644 --- a/backend/app/Controllers/Players/Deaths.ts +++ b/backend/app/Controllers/Players/Deaths.ts @@ -1,35 +1,29 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { DeathService } from 'App/Services' +interface PlayerDeath { + id: number, + date: number, + level: number +} +interface Death { + player_name: String, + monster_name: String, + player_exists: Number +} export default class PlayerDeathsController { - public async show({ request, response }: HttpContextContract) { + public deathService: DeathService = new DeathService(); + + public async show(ctx: HttpContextContract) { try { - const { remote_url } = request.body(); + const { remote_url } = ctx.request.body(); const deaths: Object[] = []; - const player_deaths = await Database - .from('player_deaths') - .select('id', 'date', 'level') - .where('player_id', request.param('id')) - .orderBy('date', 'desc') - .limit(10); + const player_deaths: PlayerDeath[] = await this.deathService.getDeathsByCharacterId(ctx.request.param('id')) as PlayerDeath[]; for(let death of player_deaths) { - const killers = await Database - .from('killers') - .leftJoin('environment_killers', 'environment_killers.kill_id', '=', 'killers.id') - .leftJoin('player_killers', 'player_killers.kill_id', '=', 'killers.id') - .leftJoin('players', 'players.id', '=', 'player_killers.player_id') - .select( - 'environment_killers.name as monster_name', - 'players.name as player_name', - 'players.deleted as player_exists', - ) - .where('killers.death_id', death.id) - .orderBy('killers.final_hit', 'desc') - .orderBy('killers.id', 'asc') - .limit(10); + const killers: Death[] = await this.deathService.getInfoDeathCharacterById(death.id) as Death[]; let description = ''; let i = 0; @@ -75,11 +69,11 @@ export default class PlayerDeathsController { 'description': description + '.' }) } - return response.status(200).send({ result: deaths}); + return ctx.response.status(200).send({ result: deaths}); } catch(err) { console.log('Error getPlayerDeaths Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) } } } diff --git a/backend/app/Controllers/Players/Items.ts b/backend/app/Controllers/Players/Items.ts index 3317e94..4530239 100644 --- a/backend/app/Controllers/Players/Items.ts +++ b/backend/app/Controllers/Players/Items.ts @@ -1,21 +1,18 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { ItemService } from 'App/Services' export default class PlayerItemsController { - public async show({ request, response }: HttpContextContract) { + public itemService: ItemService = new ItemService(); + + public async show(ctx: HttpContextContract) { try { - const items = await Database - .from('player_items') - .select('pid', 'itemtype') - .where('player_id', request.param('id')) - .andWhere('pid', '>', 0) - .andWhere('pid', '<', 11); + const items = await this.itemService.getCharacterEquipments(ctx.request.param('id')); const empty_slots = ["", "no_helmet", "no_necklace", "no_backpack", "no_armor", "no_handright", "no_handleft", "no_legs", "no_boots", "no_ring", "no_ammo"]; const name_slots = ['', 'helmet', 'necklace', 'backpack', 'armor', 'handright', 'handleft', 'legs', 'boots', 'ring', 'ammo']; - const newOrder = [0, 2, 1, 3, 5, 4, 6, 8, 10, 7, 9 ] + const newOrder = [0, 2, 1, 3, 5, 4, 6, 8, 10, 7, 9]; const equipment: Object[] = []; @@ -46,10 +43,10 @@ export default class PlayerItemsController { newEquipment.shift(); - return response.status(200).send({ result: newEquipment}); + return ctx.response.status(200).send({ result: newEquipment}); } catch(err) { console.log('Error getPlayerItems Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) } } } diff --git a/backend/app/Controllers/Players/Main.ts b/backend/app/Controllers/Players/Main.ts index 80c5f10..0fcbabc 100644 --- a/backend/app/Controllers/Players/Main.ts +++ b/backend/app/Controllers/Players/Main.ts @@ -1,35 +1,124 @@ -import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { + HttpContextContract +} from '@ioc:Adonis/Core/HttpContext' + +import { + DeleteValidator, + NameValidator +} from 'App/Validators/Character' + +import { + Player +} from 'App/Models' + +import { + Account, + Character, + CharacterRepository, + CharacterView, + HouseService +} from 'App/Services' + +import Env from '@ioc:Adonis/Core/Env' export default class PlayersController { - public async show({ request, response }: HttpContextContract) { + public character: Character = new Character(); + public characterRepository: CharacterRepository = new CharacterRepository(); + public characterView: CharacterView = new CharacterView(); + public account: Account = new Account(); + public houseService: HouseService = new HouseService(); + + public async show(ctx: HttpContextContract) { try { - let name = request.param('name'); - - name = await name - .replace(/%20/g, " ") - .replace(/'+'/g, " ") - .replace(/'/g, "") - .replace(/%27/g, "") - .replace(/-/g, "") - .replace(/"/g, "") - .replace(/%22/g, ""); - - const player = await Database - .from('players') - .select('id', 'name', 'sex', 'vocation', 'level', 'maglevel', 'lastlogin', 'healthmax', 'manamax', 'online', 'created') - .where('name', name); - return response.status(200).send({ result: player}); + const character = await this.characterView.findByName(ctx.request.param('name')); + return ctx.response.status(200).send({ result: character}); } catch(err) { - console.log('Error getPlayer Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) + console.log('Error getPlayer: ', err); + return ctx.response.status(400).send({ message: 'Character not found!'}) } } - public async edit({}: HttpContextContract) {} + public async changeName(ctx: HttpContextContract) { + try { + if (!Env.get('CHANGE_NAME')) { + return ctx.response.status(404).send({ message: 'Change character name is disabled.' }); + } + + const data = await ctx.request.validate(NameValidator); + + const account = ctx.auth.user; + + if (!account || !account.id) { + return ctx.response.unauthorized(); + } + + if (account.premium_points < Env.get('POINTS_TO_CHANGE_NAME')) { + return ctx.response.status(404).send({ + message: "You don't have the points needed to change the name. It is necessary: " + Env.get('POINTS_TO_CHANGE_NAME') + " points." + }); + } + + const character: Player[] = await this.characterView.findByIdAndAccount(data.character_id, account.id) as Player[]; + + if (!character.length) + return ctx.response.status(404).send({ message: 'The character does not belong to your account.' }); + + if (character[0].online === 1) + return ctx.response.status(404).send({ message: 'The character cannot be online.' }); + + const updateCharacter = await this.character.updateName(data.character_id, data.new_name); + + await this.account.removePremiumPoints(account.id, Env.get('POINTS_TO_CHANGE_NAME')); + + if (!updateCharacter) + return ctx.response.status(404).send({ message: "Error. Can't change character name. Probably problem with database. Please try again later or contact with admin." }); + + return ctx.response.status(200).send({ status: 200, message: "The character " + character[0].name + " name has been changed to " + data.new_name + "." }); + } catch (err) { + console.log('Error changing player name: ', err); + return ctx.response.status(400).send({ message: 'Character not found!'}) + } + } - public async update({}: HttpContextContract) {} + public async destroy(ctx: HttpContextContract) { + try { + const data = await ctx.request.validate(DeleteValidator); - public async destroy({}: HttpContextContract) {} + const account = ctx.auth.user; + + if (!account || !account.id) + return ctx.response.unauthorized(); + + const verifyPassword = await this.account.validatePassword(account.id, data.password); + + if (!verifyPassword) + return ctx.response.status(404).send({ message: 'Wrong password.' }); + + const character: Player[] = await this.characterView.findByIdAndAccount(data.character_id, account.id) as Player[]; + + if (!character.length) + return ctx.response.status(404).send({ message: 'The character does not belong to your account.' }); + + if (character[0].online === 1) + return ctx.response.status(404).send({ message: 'You cannot delete a character that is online.' }); + + if (character[0].deleted === 1) + return ctx.response.status(404).send({ message: 'This character is already deleted.' }); + + const house = await this.houseService.findByOwnerId(data.character_id); + + if (house.length) + return ctx.response.status(404).send({ message: 'You cannot delete a character that has a house.' }); + + const updateCharacter = await this.characterRepository.delete(data.character_id); + + if (!updateCharacter) + return ctx.response.status(404).send({ message: "Error. Unable to delete character. Probably problem with database. Please try again later or contact with admin." }); + + return ctx.response.status(200).send({ status: 200, message: "The character " + character[0].name + " has been deleted." }); + } catch (err) { + + } + } } diff --git a/backend/app/Controllers/Players/Skills.ts b/backend/app/Controllers/Players/Skills.ts index e441634..ce40dcc 100644 --- a/backend/app/Controllers/Players/Skills.ts +++ b/backend/app/Controllers/Players/Skills.ts @@ -1,20 +1,17 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { SkillView } from 'App/Services' export default class PlayerSkillController { - public async show({ request, response }: HttpContextContract) { + public skillView: SkillView = new SkillView(); + + public async show(ctx: HttpContextContract) { try { - const playerSkills = await Database - .from('players') - .join('player_skills', 'players.id', '=', 'player_skills.player_id') - .select('player_skills.skillid', 'player_skills.value') - .where('players.id', request.param('id')) - .andWhere('player_skills.skillid', '<>', 6); - return response.status(200).send({ result: playerSkills}); + const playerSkills = await this.skillView.getCharacterSkills(ctx.request.param('id')); + return ctx.response.status(200).send({ result: playerSkills}); } catch(err) { console.log('Error getPlayerSkills Query: ', err); - return response.status(400).send({ message: 'An error occurred, check the api console.'}) + return ctx.response.status(400).send({ message: 'An error occurred, check the api console.'}) } } } diff --git a/backend/app/Controllers/Players/Storage.ts b/backend/app/Controllers/Players/Storage.ts index 6599c15..252a1c5 100644 --- a/backend/app/Controllers/Players/Storage.ts +++ b/backend/app/Controllers/Players/Storage.ts @@ -1,17 +1,14 @@ import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' -import Database from '@ioc:Adonis/Lucid/Database' +import { StorageService } from 'App/Services' export default class PlayerStorageController { + public storageService: StorageService = new StorageService(); + public async show({ request, response }: HttpContextContract) { try { - const playerStorage = await Database - .from('player_storage') - .select('player_storage.key', 'player_storage.value') - .where('player_storage.player_id', request.param('id')) - .andWhere('player_storage.key', request.param('key')); + const playerStorage = await this.storageService.getCharacterStorage(request.param('id'), request.param('key')); return response.status(200).send({ result: playerStorage}); - } catch(err) { console.log('Error getPlayerStorage Query: ', err); return response.status(400).send({ message: 'An error occurred, check the api console.'}) diff --git a/backend/app/Models/Items.ts b/backend/app/Models/Items.ts new file mode 100644 index 0000000..9af1d7b --- /dev/null +++ b/backend/app/Models/Items.ts @@ -0,0 +1,24 @@ +import { BaseModel, column } from '@ioc:Adonis/Lucid/Orm' + +export default class Item extends BaseModel { + @column({ isPrimary: true }) + public player_id: number + + @column() + public pid: number + + @column() + public sid: number + + @column() + public itemtype: number + + @column() + public count: number + + @column() + public attributes: string + + @column() + public serial: string +} diff --git a/backend/app/Models/index.ts b/backend/app/Models/index.ts index 16f69a4..b08b7a7 100644 --- a/backend/app/Models/index.ts +++ b/backend/app/Models/index.ts @@ -1,4 +1,5 @@ export { default as Account } from './Account'; export { default as AccountKey } from './AccountKey'; -export { default as Player } from './Player'; -export { default as News } from './New'; \ No newline at end of file +export { default as Item } from './Items'; +export { default as News } from './New'; +export { default as Player } from './Player'; \ No newline at end of file diff --git a/backend/app/Services/AccountService.ts b/backend/app/Services/AccountService.ts new file mode 100644 index 0000000..9cc56d1 --- /dev/null +++ b/backend/app/Services/AccountService.ts @@ -0,0 +1,92 @@ +import { Account as AccountModel } from 'App/Models' +import Database from '@ioc:Adonis/Lucid/Database' +import encrypt from 'js-sha1' + +class Account { + public async removePremiumPoints(account_id: number, premium_points: number): Promise { + try { + const account = await Database.from('accounts').select('premium_points').where('id', '=', account_id); + + return await Database.from('accounts').where('id', '=', account_id).update({ premium_points: account[0].premium_points - premium_points }); + } catch (err) { + console.log(err); + return err; + } + } + + public async validatePassword(account_id: number, password: string): Promise { + try { + return await AccountModel.query().where('id', account_id).where('password', encrypt(password)).firstOrFail(); + } catch (err) { + console.log(err); + return err; + } + } + + public async validateName(account_id: number, name: string): Promise{ + try { + return await Database + .from('accounts') + .select('id') + .where('name', '=', name) + .andWhere('id', '<>', account_id); + } catch (err) { + console.log(err); + return err; + } + } +} + +class AccountView { + public async getTotalAccounts(): Promise { + try { + return await Database + .from('accounts') + .count('* as total'); + } catch (err) { + console.log(err); + return err; + } + } + + public async getAccountByName(name: string): Promise { + try { + return await Database + .from('accounts') + .select('id', 'name', 'premdays', 'email', 'group_id', 'web_flags', 'premium_points', 'key') + .where('name', '=', name); + } catch (err) { + console.log(err); + return err; + } + } + + public async getTopPremiumPoints(): Promise { + try { + return await Database + .from('accounts') + .select('premium_points', 'name') + .orderBy('premium_points', 'desc') + .limit(10); + } catch (err) { + console.log(err); + return err; + } + } +} + +class AccountRepository { + public async update(account_id: number, data: any): Promise { + try { + return await Database + .from('accounts') + .where('id', '=', account_id) + .update(data); + } catch (err) { + console.log(err); + return err; + } + } +} + +export { Account, AccountRepository, AccountView }; \ No newline at end of file diff --git a/backend/app/Services/CharacterService.ts b/backend/app/Services/CharacterService.ts new file mode 100644 index 0000000..8a61f72 --- /dev/null +++ b/backend/app/Services/CharacterService.ts @@ -0,0 +1,188 @@ +import Database from '@ioc:Adonis/Lucid/Database' + +class Character { + public async insertSkill(character_id: number, skill_id: number, value: number = 10, count: number = 0): Promise { + try { + return await Database.table('player_skills').insert({ + player_id: character_id, + skillid: skill_id, + value: value, + count: count + }); + } catch (err) { + console.log(err); + return err; + } + } + + public async insertItems(character_id: number, pid: number, sid: number, itemtype: number, count: number, attributes: string): Promise { + try { + return await Database.table('player_skills').insert({ + player_id: character_id, + pid, + sid, + itemtype, + count, + attributes + }); + } catch (err) { + console.log(err); + return err; + } + } + + public async updateRankId(character_id: number, rank_id: number): Promise { + try { + return await Database.from('players').where('id', '=', character_id).update({ rank_id }); + } catch (err) { + console.log(err); + return err; + } + } + + public async updateName(character_id: number, new_name: string): Promise { + try { + return await Database.from('players').where('id', '=', character_id).update({ name: new_name }); + } catch (err) { + console.log(err); + return err; + } + } +} + +class CharacterView { + public async findById(character_id: number): Promise { + try { + return await Database + .from('players') + .select('*') + .where('id', character_id); + } catch (err) { + console.log(err); + return err; + } + } + + public async findByName(name: string): Promise { + try { + name = name.replace(/%20/g, " ").replace(/'+'/g, " ").replace(/'/g, "").replace(/%27/g, "").replace(/-/g, "").replace(/"/g, "").replace(/%22/g, ""); + + return await Database + .from('players') + .select('*') + .where('name', name); + } catch (err) { + console.log(err); + return err; + } + } + + public async findByIdAndAccount(character_id: number, account_id: number): Promise { + try { + return await Database + .from('players') + .select('name', 'deleted', 'online', 'rank_id') + .where('id', '=', character_id) + .andWhere('account_id', '=', account_id); + } catch (err) { + console.log(err); + return err; + } + } + + public async getByAccount(account_id: number): Promise { + try { + return await Database + .from('players') + .select('id', 'level', 'name', 'deleted', 'online', 'vocation') + .where('account_id', '=', account_id); + } catch (err) { + console.log(err); + return err; + } + } + + public async getItems(character_id: number): Promise { + try { + return await Database.from('player_items').select('*').where('player_id', '=', character_id); + } catch (err) { + console.log(err); + return err; + } + } + + public async getTotalCharacters(): Promise { + try { + return await Database.from('players').count('* as total'); + } catch (err) { + console.log(err); + return err; + } + } + + public async checkSkillId(character_id: number, skill_id: number): Promise { + try { + return await Database.from('player_skills').select('skillid').where('player_id', '=', character_id).andWhere('skillid', '=', skill_id); + } catch (err) { + console.log(err); + return err; + } + } + + public async getTotalVocations(): Promise { + try { + return await Database + .from('players') + .select('vocation') + .count('* as total') + .groupBy('vocation'); + } catch (err) { + console.log(err); + return err; + } + } +} +class CharacterRepository { + public async create(newPlayer: Object): Promise { + try { + return await Database.table('players').returning('id').insert(newPlayer); + } catch (err) { + console.log(err); + return err; + } + } + + public async delete(character_id: number): Promise { + try { + return await Database.from('players').where('id', '=', character_id).update({ deleted: 1 }); + } catch (err) { + console.log(err); + return err; + } + } + + public async update(data: { id: number, name: string }): Promise { + try { + const character = await Database + .from('players') + .select('id') + .where('name', '=', data.name) + .andWhere('id', '<>', data.id); + + if (character.length) + return "Error. The username is already used."; + + const affectedRows = await Database.from('players').where('id', '=', data.id).update(data); + + if (!affectedRows) + return "Character not found."; + + return "Character successfully updated."; + } catch (err) { + console.log(err); + return err; + } + } +} + +export { Character, CharacterView, CharacterRepository }; \ No newline at end of file diff --git a/backend/app/Services/DeathService.ts b/backend/app/Services/DeathService.ts new file mode 100644 index 0000000..0a2a5b7 --- /dev/null +++ b/backend/app/Services/DeathService.ts @@ -0,0 +1,69 @@ +import Database from '@ioc:Adonis/Lucid/Database' + +export default class DeathService { + public async getDeathsByCharacterId(character_id: number): Promise { + try { + return await Database + .from('player_deaths') + .select('id', 'date', 'level') + .where('player_id', character_id) + .orderBy('date', 'desc') + .limit(10); + } catch (err) { + console.log(err); + return err; + } + } + + public async getInfoDeathCharacterById(death_id: number): Promise { + try { + return await Database + .from('killers') + .leftJoin('environment_killers', 'environment_killers.kill_id', '=', 'killers.id') + .leftJoin('player_killers', 'player_killers.kill_id', '=', 'killers.id') + .leftJoin('players', 'players.id', '=', 'player_killers.player_id') + .select( + 'environment_killers.name as monster_name', + 'players.name as player_name', + 'players.deleted as player_exists', + ) + .where('killers.death_id', death_id) + .orderBy('killers.final_hit', 'desc') + .orderBy('killers.id', 'asc') + .limit(10); + } catch (err) { + console.log(err); + return err; + } + } + + public async getLastKills(page: number, limit: number): Promise { + try { + return await Database + .from('player_deaths') + .innerJoin('players', 'players.id', 'player_deaths.player_id') + .select('player_deaths.id', 'player_deaths.date', 'player_deaths.level', 'players.name') + .orderBy('player_deaths.date', 'desc') + .paginate(page, limit); + } catch (err) { + console.log(err); + return err; + } + } + + public async getKillers(death_id: number): Promise { + try { + return await Database + .from('killers') + .leftJoin('environment_killers', 'environment_killers.kill_id', 'killers.id') + .leftJoin('player_killers', 'player_killers.kill_id', 'killers.id') + .leftJoin('players', 'players.id', 'player_killers.player_id') + .select('environment_killers.name AS monster_name', 'players.name AS player_name', 'players.deleted AS player_exists') + .where('killers.death_id', '=', death_id) + .orderBy('killers.final_hit', 'desc'); + } catch (err) { + console.log(err); + return err; + } + } +} \ No newline at end of file diff --git a/backend/app/Services/GuildService.ts b/backend/app/Services/GuildService.ts new file mode 100644 index 0000000..5156cf1 --- /dev/null +++ b/backend/app/Services/GuildService.ts @@ -0,0 +1,122 @@ +import Database from '@ioc:Adonis/Lucid/Database' + +class GuildView { + public async getTotalGuilds(): Promise { + try { + return await Database + .from('guilds') + .count('* as total'); + } catch (err) { + console.log(err); + return err; + } + } + + public async getGuildById(guild_id: number): Promise { + try { + return await Database + .from('guilds') + .innerJoin('guild_ranks', 'guild_ranks.guild_id', 'guilds.id') + .select('guild_ranks.id as rank_id') + .where('guilds.id', '=', guild_id) + .andWhere('guild_ranks.level', '=', 3); + } catch (err) { + console.log(err); + return err; + } + } + + public async getGuildByName(name: string): Promise { + try { + name = name.replace(/%20/g, " ").replace(/'+'/g, " ").replace(/'/g, "").replace(/%27/g, "").replace(/-/g, "").replace(/"/g, "").replace(/%22/g, ""); + + return await Database + .from('guilds') + .innerJoin('players', 'players.id', 'guilds.ownerid') + .select( + 'guilds.id', + 'guilds.name', + 'guilds.description', + 'guilds.ownerid as owner_id', + 'guilds.creationdata as creation_data', + 'players.name as owner_name', + ) + .where('guilds.name', '=', name); + } catch (err) { + console.log(err); + return err; + } + } + + public async getGuildRanks(guild_id: number): Promise { + try { + return await Database + .from('guild_ranks') + .select('id') + .where('guild_id', '=', guild_id); + } catch (err) { + console.log(err); + return err; + } + } + + public async getGuildMembers(guild_id: number): Promise { + try { + return await Database.from('guilds') + .innerJoin('guild_ranks', 'guild_ranks.guild_id', '=', 'guilds.id') + .innerJoin('players', 'players.rank_id', 'guild_ranks.id') + .select( + 'guild_ranks.level', + 'guild_ranks.name as rank_name', + 'players.id', + 'players.name', + 'players.vocation', + 'players.level as player_level', + 'players.online' + ) + .where('guilds.id', '=', guild_id) + .orderBy('guild_ranks.level', 'desc'); + } catch (err) { + console.log(err); + return err; + } + } + + public async getGuilds(page: number, limit: number): Promise { + try { + return await Database + .from('guilds') + .select('id', 'name', 'motd', 'logo_name', 'description') + .paginate(page, limit); + } catch (err) { + console.log(err); + return err; + } + } + + public async getCharactersWithGuild(account_id: number): Promise { + try { + return await Database + .from('players') + .select('id', 'name') + .where('account_id', '=', account_id) + .andWhere('rank_id', '=', 0); + } catch (err) { + console.log(err); + return err; + } + } +} + +class GuildRepository { + public async create(newGuild: object): Promise { + try { + return await Database.table('guilds').returning('id').insert(newGuild); + } catch (err) { + console.log(err); + return err; + } + } +} + +export { GuildView, GuildRepository} \ No newline at end of file diff --git a/backend/app/Services/HighscoresService.ts b/backend/app/Services/HighscoresService.ts new file mode 100644 index 0000000..eb1cc80 --- /dev/null +++ b/backend/app/Services/HighscoresService.ts @@ -0,0 +1,60 @@ +import Database from '@ioc:Adonis/Lucid/Database' +import { Skills } from 'Contracts/enums/Skills' + +export default class HighscoresService { + public async topRankPlayers(): Promise { + return await Database + .from('players') + .select('id', 'name', 'level', 'vocation', 'experience', 'online') + .where('deleted', '=', 0) + .andWhere('group_id', '<', 4) + .orderBy('experience', 'desc') + .limit(5); + } + + public async find(page: number, limit: number, type: string): Promise { + if (type === 'Experience') + return await Database + .from('players') + .select('name', 'vocation', 'level', 'experience', 'online') + .where('deleted', '=', 0) + .andWhere('group_id', '<', 4) + .orderBy('experience', 'desc') + .paginate(page, limit); + + else if (type === 'Magic Level') + return await Database + .from('players') + .select('name', 'vocation', 'maglevel as value', 'experience', 'online') + .where('deleted', '=', 0) + .andWhere('group_id', '<', 4) + .orderBy('maglevel', 'desc') + .paginate(page, limit); + + else if (type === 'Frags') + return await Database + .from('players') + .innerJoin('player_killers', 'player_killers.player_id', 'players.id') + .select('players.name', 'players.vocation', 'players.online') + .count('player_killers.player_id as value') + .where('players.deleted', '=', 0) + .andWhere('players.group_id', '<', 4) + .groupBy('players.name') + .orderBy('value', 'desc') + .paginate(page, limit); + + else { + const skill = Skills.find((skill) => skill.text === type)?.value; + + return await Database + .from('players') + .innerJoin('player_skills', 'player_skills.player_id', 'players.id') + .select('players.name', 'players.vocation', 'player_skills.value', 'players.online') + .where('players.deleted', '=', 0) + .andWhere('players.group_id', '<', 4) + .andWhere('player_skills.skillid', '=', skill || 0) + .orderBy('player_skills.value', 'desc') + .paginate(page, limit); + } + } +} \ No newline at end of file diff --git a/backend/app/Services/HouseService.ts b/backend/app/Services/HouseService.ts new file mode 100644 index 0000000..7cadee4 --- /dev/null +++ b/backend/app/Services/HouseService.ts @@ -0,0 +1,12 @@ +import Database from '@ioc:Adonis/Lucid/Database' + +export default class HouseService { + public async findByOwnerId(character_id: number): Promise { + try { + return await Database.from('houses').select('id').where('owner', '=', character_id); + } catch (err) { + console.log(err); + return err; + } + } +} \ No newline at end of file diff --git a/backend/app/Services/ItemService.ts b/backend/app/Services/ItemService.ts new file mode 100644 index 0000000..02f5482 --- /dev/null +++ b/backend/app/Services/ItemService.ts @@ -0,0 +1,17 @@ +import Database from '@ioc:Adonis/Lucid/Database' + +export default class ItemService { + public async getCharacterEquipments(character_id: number): Promise { + try { + return await Database + .from('player_items') + .select('pid', 'itemtype') + .where('player_id', character_id) + .andWhere('pid', '>', 0) + .andWhere('pid', '<', 11); + } catch (err) { + console.log(err); + return err; + } + } +} \ No newline at end of file diff --git a/backend/app/Services/NewsService.ts b/backend/app/Services/NewsService.ts new file mode 100644 index 0000000..14a7383 --- /dev/null +++ b/backend/app/Services/NewsService.ts @@ -0,0 +1,61 @@ +import Database from '@ioc:Adonis/Lucid/Database' + +class News { +} + +class NewsView { + public async findNewsById(news_id: number): Promise { + try { + return await Database + .from('electro_news') + .select('*') + .where('id', '=', news_id) + } catch (err) { + console.log(err); + return err; + } + } + public async getNews(page: number, limit: number): Promise { + try { + return await Database + .from('electro_news') + .select('id', 'title', 'body', 'created_at') + .where('hidden', '=', 0) + .orderBy('created_at', 'desc') + .paginate(page, limit); + } catch (err) { + console.log(err); + return err; + } + } +} + +class NewsRepository { + public async create(news: Object): Promise { + try { + return await Database.table('electro_news').returning('id').insert(news); + } catch (err) { + console.log(err); + return err; + } + } + + public async update(news_id: number, data: any): Promise { + try { + return await Database + .from('electro_news') + .where('id', '=', news_id) + .update({ + title: data.title, + body: data.description, + hidden: data.hidden ? 1 : 0, + updated_at: new Date() + }); + } catch (err) { + console.log(err); + return err; + } + } +} + +export { News, NewsRepository, NewsView }; \ No newline at end of file diff --git a/backend/app/Services/OnlineService.ts b/backend/app/Services/OnlineService.ts new file mode 100644 index 0000000..148030f --- /dev/null +++ b/backend/app/Services/OnlineService.ts @@ -0,0 +1,31 @@ +import Database from '@ioc:Adonis/Lucid/Database' + +export default class OnlineService { + public async getPlayersOnline(): Promise { + try { + return await Database + .from('players') + .innerJoin('accounts', 'accounts.id', 'players.account_id') + .select('accounts.country', 'players.skull', 'players.skulltime', 'players.name', 'players.level', 'players.vocation') + .where('players.online', '>', '0') + .orderBy('experience', 'desc'); + } catch (err) { + console.log(err); + return err; + } + } + + public async getRecord(world_id): Promise { + try { + return await Database + .from('server_record') + .select('record', 'timestamp') + .where('world_id', '=', world_id) + .orderBy('record', 'desc') + .limit(1); + } catch (err) { + console.log(err); + return err; + } + } +} \ No newline at end of file diff --git a/backend/app/Services/SkillService.ts b/backend/app/Services/SkillService.ts new file mode 100644 index 0000000..a97dd24 --- /dev/null +++ b/backend/app/Services/SkillService.ts @@ -0,0 +1,36 @@ +import Database from '@ioc:Adonis/Lucid/Database' + +class Skill { + public async updateCharacterSkill(character_id: number, skills: any): Promise { + try { + return await Database + .from('player_skills') + .where('player_id', '=', character_id) + .andWhere('skillid', '=', skills.skillid) + .update({ + skillid: skills.skillid, + value: skills.value, + count: skills.count + }); + } catch (err) { + console.log(err); + return err; + } + } +} + +class SkillView { + public async getCharacterSkills(character_id: number): Promise { + try { + return await Database + .from('player_skills') + .select('*') + .where('player_id', '=', character_id); + } catch (err) { + console.log(err); + return err; + } + } +} + +export { Skill, SkillView }; \ No newline at end of file diff --git a/backend/app/Services/StorageService.ts b/backend/app/Services/StorageService.ts new file mode 100644 index 0000000..ac5c316 --- /dev/null +++ b/backend/app/Services/StorageService.ts @@ -0,0 +1,16 @@ +import Database from '@ioc:Adonis/Lucid/Database' + +export default class StorageService { + public async getCharacterStorage(character_id: number, storage: string): Promise { + try { + return await Database + .from('player_storage') + .select('player_storage.key', 'player_storage.value') + .where('player_storage.player_id', character_id) + .andWhere('player_storage.key', storage); + } catch (err) { + console.log(err); + return err; + } + } +} \ No newline at end of file diff --git a/backend/app/Services/index.ts b/backend/app/Services/index.ts new file mode 100644 index 0000000..19b7181 --- /dev/null +++ b/backend/app/Services/index.ts @@ -0,0 +1,37 @@ +export { + Account, + AccountRepository, + AccountView +} from './AccountService'; + +export { + Character, + CharacterRepository, + CharacterView +} from './CharacterService'; + +export { default as DeathService } from './DeathService'; + +export { + GuildRepository, + GuildView +} from './GuildService'; + +export { default as HighscoresService } from './HighscoresService'; +export { default as ItemService } from './ItemService'; +export { default as HouseService } from './HouseService'; + +export { + News, + NewsRepository, + NewsView +} from './NewsService'; + +export { default as OnlineService } from './OnlineService'; + +export { + Skill, + SkillView +} from './SkillService'; + +export { default as StorageService } from './StorageService'; \ No newline at end of file diff --git a/backend/app/Validators/Account/Character/index.ts b/backend/app/Validators/Account/Character/index.ts index 31db118..70f4f41 100644 --- a/backend/app/Validators/Account/Character/index.ts +++ b/backend/app/Validators/Account/Character/index.ts @@ -1,3 +1 @@ -export { default as StoreValidator } from './StoreValidator' -export { default as UpdateValidator } from './UpdateValidator' -export { default as DeleteValidator } from './DeleteValidator' \ No newline at end of file +export { default as StoreValidator } from './StoreValidator' \ No newline at end of file diff --git a/backend/app/Validators/Account/Character/DeleteValidator.ts b/backend/app/Validators/Character/DeleteValidator.ts similarity index 100% rename from backend/app/Validators/Account/Character/DeleteValidator.ts rename to backend/app/Validators/Character/DeleteValidator.ts diff --git a/backend/app/Validators/Account/Character/UpdateValidator.ts b/backend/app/Validators/Character/NameValidator.ts similarity index 100% rename from backend/app/Validators/Account/Character/UpdateValidator.ts rename to backend/app/Validators/Character/NameValidator.ts diff --git a/backend/app/Validators/Character/index.ts b/backend/app/Validators/Character/index.ts new file mode 100644 index 0000000..737dc3f --- /dev/null +++ b/backend/app/Validators/Character/index.ts @@ -0,0 +1,2 @@ +export { default as NameValidator } from './NameValidator' +export { default as DeleteValidator } from './DeleteValidator' \ No newline at end of file diff --git a/backend/app/Validators/Dashboard/Accounts/UpdateValidator.ts b/backend/app/Validators/Dashboard/Accounts/UpdateValidator.ts new file mode 100644 index 0000000..6f7fb18 --- /dev/null +++ b/backend/app/Validators/Dashboard/Accounts/UpdateValidator.ts @@ -0,0 +1,30 @@ +import { schema, rules } from '@ioc:Adonis/Core/Validator' +import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' + +export default class UpdateValidator { + constructor(protected ctx: HttpContextContract) {} + + public schema = schema.create({ + id: schema.number([rules.required(), rules.exists({ table: 'accounts', column: 'id' })]), + name: schema.string({ escape: true }, [ + rules.required(), + rules.alpha(), + rules.minLength(3), + rules.maxLength(20), + ]), + email: schema.string({ trim: true }, [rules.required()]), + premdays: schema.number.optional(), + group_id: schema.number.optional(), + web_flags: schema.number.optional(), + premium_points: schema.number.optional() + }) + + public messages = { + required: 'The {{ field }} is required to create a new character', + minLength: 'Name is too long. Min length {{ options.minLength }} letters', + maxLength: 'Name is too short. Max length {{ options.maxLength }} letters', + alpha: 'Invalid character name.', + 'name.unique': 'Character name not available', + 'name.notIn': 'The name contains an invalid name.', + } +} diff --git a/backend/app/Validators/Dashboard/Accounts/index.ts b/backend/app/Validators/Dashboard/Accounts/index.ts new file mode 100644 index 0000000..cfeb80b --- /dev/null +++ b/backend/app/Validators/Dashboard/Accounts/index.ts @@ -0,0 +1 @@ +export { default as UpdateValidator } from './UpdateValidator' \ No newline at end of file diff --git a/backend/app/Validators/Dashboard/CharacterSkills/UpdateValidator.ts b/backend/app/Validators/Dashboard/CharacterSkills/UpdateValidator.ts new file mode 100644 index 0000000..637bc17 --- /dev/null +++ b/backend/app/Validators/Dashboard/CharacterSkills/UpdateValidator.ts @@ -0,0 +1,20 @@ +import { schema, rules } from '@ioc:Adonis/Core/Validator' +import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' + +export default class UpdateValidator { + constructor(protected ctx: HttpContextContract) {} + + public schema = schema.create({ + id: schema.number([rules.required(), rules.exists({ table: 'players', column: 'id' })]), + skills: schema.array().members( + schema.object().members({ + player_id: schema.number(), + skillid: schema.number(), + value: schema.number(), + count: schema.number() + }) + ), + }) + + public messages = {}; +} diff --git a/backend/app/Validators/Dashboard/CharacterSkills/index.ts b/backend/app/Validators/Dashboard/CharacterSkills/index.ts new file mode 100644 index 0000000..cfeb80b --- /dev/null +++ b/backend/app/Validators/Dashboard/CharacterSkills/index.ts @@ -0,0 +1 @@ +export { default as UpdateValidator } from './UpdateValidator' \ No newline at end of file diff --git a/backend/app/Validators/Dashboard/Characters/UpdateValidator.ts b/backend/app/Validators/Dashboard/Characters/UpdateValidator.ts new file mode 100644 index 0000000..5958600 --- /dev/null +++ b/backend/app/Validators/Dashboard/Characters/UpdateValidator.ts @@ -0,0 +1,114 @@ +import { schema, rules } from '@ioc:Adonis/Core/Validator' +import { HttpContextContract } from '@ioc:Adonis/Core/HttpContext' + +export default class UpdateValidator { + constructor(protected ctx: HttpContextContract) {} + + public schema = schema.create({ + id: schema.number([rules.required(), rules.exists({ table: 'players', column: 'id' })]), + name: schema.string({ escape: true }, [ + rules.required(), + rules.alpha({ + allow: ['space'] + }), + rules.minLength(3), + rules.maxLength(20), + ]), + world_id: schema.number.optional(), + group_id: schema.number.optional(), + account_id: schema.number.optional([rules.exists({ table: 'accounts', column: 'id'})]), + level: schema.number.optional(), + vocation: schema.number.optional(), + health: schema.number.optional(), + healthmax: schema.number.optional(), + experience: schema.number.optional(), + lookbody: schema.number.optional(), + lookfeet: schema.number.optional(), + lookhead: schema.number.optional(), + looklegs: schema.number.optional(), + looktype: schema.number.optional(), + lookaddons: schema.number.optional(), + maglevel: schema.number.optional(), + mana: schema.number.optional(), + manamax: schema.number.optional(), + manaspent: schema.number.optional(), + soul: schema.number.optional(), + town_id: schema.number.optional(), + posx: schema.number.optional(), + posy: schema.number.optional(), + posz: schema.number.optional(), + cap: schema.number.optional(), + sex: schema.number.optional(), + lastlogin: schema.number.optional(), + lastip: schema.number.optional(), + save: schema.number.optional(), + skull: schema.number.optional(), + skulltime: schema.number.optional(), + rank_id: schema.number.optional(), + guildnick: schema.number.optional(), + lastlogout: schema.number.optional(), + blessings: schema.number.optional(), + pvp_blessing: schema.number.optional(), + balance: schema.number.optional(), + stamina: schema.number.optional(), + direction: schema.number.optional(), + loss_experience: schema.number.optional(), + loss_mana: schema.number.optional(), + loss_skills: schema.number.optional(), + loss_containers: schema.number.optional(), + loss_items: schema.number.optional(), + premend: schema.number.optional(), + online: schema.number.optional(), + marriage: schema.number.optional(), + marrystatus: schema.number.optional(), + promotion: schema.number.optional(), + deleted: schema.number.optional(), + description: schema.string.optional(), + created: schema.number.optional(), + nick_verify: schema.number.optional(), + old_name: schema.string.optional(), + hidden: schema.number.optional(), + worldtransfer: schema.number.optional(), + comment: schema.string.optional(), + show_outfit: schema.number.optional(), + show_eq: schema.number.optional(), + show_bars: schema.number.optional(), + show_skills: schema.number.optional(), + show_quests: schema.number.optional(), + exphist_lastexp: schema.number.optional(), + exphist1: schema.number.optional(), + exphist2: schema.number.optional(), + exphist3: schema.number.optional(), + exphist4: schema.number.optional(), + exphist5: schema.number.optional(), + exphist6: schema.number.optional(), + exphist7: schema.number.optional(), + onlinetimetoday: schema.number.optional(), + onlinetime1: schema.number.optional(), + onlinetime2: schema.number.optional(), + onlinetime3: schema.number.optional(), + onlinetime4: schema.number.optional(), + onlinetime5: schema.number.optional(), + onlinetime6: schema.number.optional(), + onlinetime7: schema.number.optional(), + onlinetimeall: schema.number.optional(), + ip: schema.string.optional(), + cast: schema.number.optional(), + castViewers: schema.number.optional(), + castDescription: schema.string.optional(), + frags: schema.number.optional(), + offlinetraining_time: schema.number.optional(), + offlinetraining_skill: schema.number.optional(), + broadcasting: schema.number.optional(), + viewers: schema.number.optional() + }) + + public messages = { + required: 'The {{ field }} is required to update character', + minLength: 'Name is too long. Min length {{ options.minLength }} letters', + maxLength: 'Name is too short. Max length {{ options.maxLength }} letters', + alpha: 'Invalid character name.', + 'name.unique': 'Character name not available', + 'name.notIn': 'The name contains an invalid name.', + } +} diff --git a/backend/app/Validators/Dashboard/Characters/index.ts b/backend/app/Validators/Dashboard/Characters/index.ts new file mode 100644 index 0000000..cfeb80b --- /dev/null +++ b/backend/app/Validators/Dashboard/Characters/index.ts @@ -0,0 +1 @@ +export { default as UpdateValidator } from './UpdateValidator' \ No newline at end of file diff --git a/backend/contracts/enums/Skills.ts b/backend/contracts/enums/Skills.ts new file mode 100644 index 0000000..4ccef2c --- /dev/null +++ b/backend/contracts/enums/Skills.ts @@ -0,0 +1,9 @@ +export const Skills = [ + { value: 0, text: "Attack Speed" }, + { value: 1, text: "Club" }, + { value: 2, text: "Sword" }, + { value: 3, text: "Axe" }, + { value: 4, text: "Distance" }, + { value: 5, text: "Shielding" }, + { value: 6, text: "Fishing" }, +] \ No newline at end of file diff --git a/backend/contracts/enums/Vocations.ts b/backend/contracts/enums/Vocations.ts index 1d31718..efb8b5b 100644 --- a/backend/contracts/enums/Vocations.ts +++ b/backend/contracts/enums/Vocations.ts @@ -1,18 +1,26 @@ export const Vocations = [ { vocation_id: 1, - name: "Orc Sample" + name: "Dragon Slayer Sample" }, { vocation_id: 18, - name: "With Sample" + name: "Winter Sample" }, { vocation_id: 32, - name: "Demon Sample" + name: "Barbarian Sample" }, { vocation_id: 47, - name: "Lizard Sample" + name: "Mage Sample" + }, + { + vocation_id: 59, + name: "Mercenary Sample" + }, + { + vocation_id: 68, + name: "Warrior Sample" }, ] \ No newline at end of file diff --git a/backend/start/routes/account.ts b/backend/start/routes/account.ts index 65cc7b3..ef2e198 100644 --- a/backend/start/routes/account.ts +++ b/backend/start/routes/account.ts @@ -1,5 +1,4 @@ import Route from '@ioc:Adonis/Core/Route'; -import Env from '@ioc:Adonis/Core/Env' Route.post('/accounts/register', 'Account/Register.store'); Route.get('/accounts/register/:code', 'Account/Register.show'); @@ -12,13 +11,3 @@ Route.get('/accounts', 'Account/Main.show').middleware('auth') Route.get('/accounts/characters/:id', 'Account/Characters.show').middleware('auth'); Route.post('/accounts/create-character', 'Account/Characters.store').middleware('auth'); - -Route.get('/accounts/change-character-name', ({ response }) => { - response.status(200).send({ - enabled: Env.get('CHANGE_NAME'), - points: Env.get('POINTS_TO_CHANGE_NAME') - }); -}).middleware('auth'); - -Route.post('/accounts/change-character-name', 'Account/Characters.update').middleware('auth'); -Route.post('/accounts/delete-character', 'Account/Characters.destroy').middleware('auth'); \ No newline at end of file diff --git a/backend/start/routes/character.ts b/backend/start/routes/character.ts new file mode 100644 index 0000000..83bdaed --- /dev/null +++ b/backend/start/routes/character.ts @@ -0,0 +1,19 @@ +import Route from '@ioc:Adonis/Core/Route'; +import Env from '@ioc:Adonis/Core/Env' + +Route.get('/player/:name', 'Players/Main.show'); +Route.get('/player/:id/skills', 'Players/Skills.show'); +Route.get('/player/:id/storage/:key', 'Players/Storage.show'); +Route.post('/player/:id/deaths', 'Players/Deaths.show'); +Route.get('/player/:id/items', 'Players/Items.show'); + +// Change name +Route.get('/player/change-name', ({ response }) => { + response.status(200).send({ + enabled: Env.get('CHANGE_NAME'), + points: Env.get('POINTS_TO_CHANGE_NAME') + }); +}).middleware('auth'); +Route.post('/player/change-name', 'Players/Main.changeName').middleware('auth'); + +Route.post('/player/delete-character', 'Players/Main.destroy').middleware('auth'); \ No newline at end of file diff --git a/backend/start/routes/dashboard/accounts.ts b/backend/start/routes/dashboard/accounts.ts new file mode 100644 index 0000000..a63b903 --- /dev/null +++ b/backend/start/routes/dashboard/accounts.ts @@ -0,0 +1,4 @@ +import Route from '@ioc:Adonis/Core/Route'; + +Route.get('/dashboard/account/:name', 'Dashboard/Accounts.show').middleware('auth'); +Route.post('/dashboard/account', 'Dashboard/Accounts.update').middleware('auth'); \ No newline at end of file diff --git a/backend/start/routes/dashboard/character.ts b/backend/start/routes/dashboard/character.ts new file mode 100644 index 0000000..078d658 --- /dev/null +++ b/backend/start/routes/dashboard/character.ts @@ -0,0 +1,6 @@ +import Route from '@ioc:Adonis/Core/Route'; + +Route.get('/dashboard/character/:name', 'Dashboard/Players.show').middleware('auth'); +Route.get('/dashboard/character-skills/:id', 'Dashboard/PlayerSkills.show').middleware('auth'); +Route.post('/dashboard/character', 'Dashboard/Players.update').middleware('auth'); +Route.post('/dashboard/character-skills', 'Dashboard/PlayerSkills.update').middleware('auth'); \ No newline at end of file diff --git a/backend/start/routes/dashboard.ts b/backend/start/routes/dashboard/home.ts similarity index 64% rename from backend/start/routes/dashboard.ts rename to backend/start/routes/dashboard/home.ts index 157d004..680a1e8 100644 --- a/backend/start/routes/dashboard.ts +++ b/backend/start/routes/dashboard/home.ts @@ -1,7 +1,7 @@ import Route from '@ioc:Adonis/Core/Route'; -Route.get('/dashboard/accounts', 'Dashboard/Accounts.show').middleware('auth'); -Route.get('/dashboard/players', 'Dashboard/Players.show').middleware('auth'); +Route.get('/dashboard/accounts', 'Dashboard/Accounts.index').middleware('auth'); +Route.get('/dashboard/players', 'Dashboard/Players.index').middleware('auth'); Route.get('/dashboard/guilds', 'Dashboard/Guilds.show').middleware('auth'); Route.get('/dashboard/premium-points', 'Dashboard/PremiumPoints.show').middleware('auth'); Route.get('/dashboard/vocations', 'Dashboard/Vocations.show').middleware('auth'); \ No newline at end of file diff --git a/backend/start/routes/highscores.ts b/backend/start/routes/highscores.ts index 211270e..996f238 100644 --- a/backend/start/routes/highscores.ts +++ b/backend/start/routes/highscores.ts @@ -1,4 +1,4 @@ import Route from '@ioc:Adonis/Core/Route'; Route.get('/highscores', 'Highscores/Main.show'); -Route.get('/highscores/:page/:limit', 'Highscores/Main.getRank'); \ No newline at end of file +Route.get('/highscores/:page/:limit/:type', 'Highscores/Main.getRank'); \ No newline at end of file diff --git a/backend/start/routes/index.ts b/backend/start/routes/index.ts index 4fb6c2a..4c2090b 100644 --- a/backend/start/routes/index.ts +++ b/backend/start/routes/index.ts @@ -2,8 +2,10 @@ import Route from '@ioc:Adonis/Core/Route'; import './auth'; import './account'; import './highscores'; -import './players'; -import './dashboard'; +import './character'; +import './dashboard/home'; +import './dashboard/accounts'; +import './dashboard/character'; import './guilds'; import './online'; import './lastkills'; diff --git a/backend/start/routes/players.ts b/backend/start/routes/players.ts deleted file mode 100644 index 0ed026c..0000000 --- a/backend/start/routes/players.ts +++ /dev/null @@ -1,7 +0,0 @@ -import Route from '@ioc:Adonis/Core/Route'; - -Route.get('/player/:name', 'Players/Main.show'); -Route.get('/player/:id/skills', 'Players/Skills.show'); -Route.get('/player/:id/storage/:key', 'Players/Storage.show'); -Route.post('/player/:id/deaths', 'Players/Deaths.show'); -Route.get('/player/:id/items', 'Players/Items.show'); \ No newline at end of file diff --git a/frontend/assets/css/main.css b/frontend/assets/css/main.css index 3943bd3..21c3847 100644 --- a/frontend/assets/css/main.css +++ b/frontend/assets/css/main.css @@ -167,6 +167,11 @@ border-color: var(--red) !important; } +.btn-danger-secondary { + color: var(--red) !important; + border-color: var(--red) !important; +} + .container { width: 95% !important; } @@ -204,12 +209,17 @@ border-radius: 1.95rem; } +.theme--light.v-tabs-dashboard > .v-tabs-bar { + background-color: #2a2c32 !important; +} + .theme--light.v-tabs > .v-tabs-bar .v-tab:not(.v-tab--active), .theme--light.v-tabs > .v-tabs-bar .v-tab:not(.v-tab--active) > .v-icon, .theme--light.v-tabs > .v-tabs-bar .v-tab:not(.v-tab--active) > .v-btn, .theme--light.v-tabs > .v-tabs-bar .v-tab--disabled { color: var(--text-color) !important; } .theme--light.v-tabs-items { background-color: var(--bg-main-color) !important; + color: var(--text-color) !important; border-radius: 1.95rem; } @@ -315,7 +325,11 @@ background-color: var(--bg-dashboard-main-color); } -.theme--light.v-navigation-drawer { +#dashboard h3 { + color: var(--heading-color) !important; +} + +.dashboard-drawer { background-color: var(--bg-dashboard-main-color) !important; } @@ -332,7 +346,7 @@ } .dashboard-container { - background-color: var(--bg-dashboard-content-color) !important; + background-color: #2a2c32 !important; border-radius: 24px !important; box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 28%), @@ -362,4 +376,34 @@ .v-data-table--fixed-header > .v-data-table__wrapper > table > thead > tr > th { z-index: 0 !important; +} + +.v-application--is-ltr .v-list-item__action:last-of-type:not(:only-child), .v-application--is-ltr .v-list-item__avatar:last-of-type:not(:only-child), .v-application--is-ltr .v-list-item__icon:last-of-type:not(:only-child) { + margin-left: 0px !important; +} + +.v-application--is-ltr .v-list-group--no-action > .v-list-group__items > .v-list-item { + padding-left: 40px !important; +} + +.btn-highscores { + color: var(--heading-color); +} + +.theme--light.v-bottom-navigation { + background-color: inherit !important; + box-shadow: none !important; + color: var(--main-color) !important; +} + +.theme--light.v-select .v-select__selections { + color: var(--heading-color) !important; +} + +.theme--light.v-data-table .v-data-table__empty-wrapper { + color: var(--heading-color) !important; +} + +.theme--light.v-btn.v-btn--has-bg { + background-color: transparent !important; } \ No newline at end of file diff --git a/frontend/assets/css/tibia-custom.css b/frontend/assets/css/tibia-custom.css index fbc35a2..7151b2d 100644 --- a/frontend/assets/css/tibia-custom.css +++ b/frontend/assets/css/tibia-custom.css @@ -20,6 +20,7 @@ #app { background-color: var(--bg-main-color); + color: var(--heading-color) !important; } #header { @@ -38,4 +39,9 @@ .bg-third { background-color: rgb(255 165 0 / 23%) !important; +} + +.menu-mobile { + background-color: var(--bg-third-color) !important; + border-right: 2px solid var(--main-color) !important; } \ No newline at end of file diff --git a/frontend/assets/css/tibia-default.css b/frontend/assets/css/tibia-default.css index 7b3c579..1fc041f 100644 --- a/frontend/assets/css/tibia-default.css +++ b/frontend/assets/css/tibia-default.css @@ -38,4 +38,9 @@ .bg-third { background-color: #00ffc43b !important; +} + +.menu-mobile { + background-color: var(--bg-third-color) !important; + border-right: 2px solid var(--main-color) !important; } \ No newline at end of file diff --git a/frontend/components/atoms/routes/AccountRoutes.vue b/frontend/components/atoms/routes/AccountRoutes.vue index f622b59..f07b62e 100644 --- a/frontend/components/atoms/routes/AccountRoutes.vue +++ b/frontend/components/atoms/routes/AccountRoutes.vue @@ -53,7 +53,7 @@ import Vue from 'vue' import { auth, account } from '@/store' import { Accounts, Route } from '@/models' -import { routesAccount } from '@/utils/enum' +import { routesAccount } from '@/utils/routes' export default Vue.extend({ computed: { diff --git a/frontend/components/atoms/routes/CommunityRoutes.vue b/frontend/components/atoms/routes/CommunityRoutes.vue index 77b37e4..d495303 100644 --- a/frontend/components/atoms/routes/CommunityRoutes.vue +++ b/frontend/components/atoms/routes/CommunityRoutes.vue @@ -32,7 +32,7 @@ \ No newline at end of file diff --git a/frontend/components/molecules/dashboard/account/DashboardCharactersAccount.vue b/frontend/components/molecules/dashboard/account/DashboardCharactersAccount.vue new file mode 100644 index 0000000..e1eec7e --- /dev/null +++ b/frontend/components/molecules/dashboard/account/DashboardCharactersAccount.vue @@ -0,0 +1,39 @@ + + + \ No newline at end of file diff --git a/frontend/components/molecules/dashboard/account/DashboardFindAccount.vue b/frontend/components/molecules/dashboard/account/DashboardFindAccount.vue new file mode 100644 index 0000000..46aaa37 --- /dev/null +++ b/frontend/components/molecules/dashboard/account/DashboardFindAccount.vue @@ -0,0 +1,59 @@ + + + \ No newline at end of file diff --git a/frontend/components/molecules/dashboard/characters/DashboardCharacterForm.vue b/frontend/components/molecules/dashboard/characters/DashboardCharacterForm.vue new file mode 100644 index 0000000..ee0d08e --- /dev/null +++ b/frontend/components/molecules/dashboard/characters/DashboardCharacterForm.vue @@ -0,0 +1,184 @@ + + + \ No newline at end of file diff --git a/frontend/components/molecules/dashboard/characters/DashboardCharacterInformations.vue b/frontend/components/molecules/dashboard/characters/DashboardCharacterInformations.vue new file mode 100644 index 0000000..bd3c20e --- /dev/null +++ b/frontend/components/molecules/dashboard/characters/DashboardCharacterInformations.vue @@ -0,0 +1,122 @@ + + + \ No newline at end of file diff --git a/frontend/components/molecules/dashboard/characters/DashboardCharacterOutfit.vue b/frontend/components/molecules/dashboard/characters/DashboardCharacterOutfit.vue new file mode 100644 index 0000000..429fe49 --- /dev/null +++ b/frontend/components/molecules/dashboard/characters/DashboardCharacterOutfit.vue @@ -0,0 +1,108 @@ + + + \ No newline at end of file diff --git a/frontend/components/molecules/dashboard/characters/DashboardCharacterSkills.vue b/frontend/components/molecules/dashboard/characters/DashboardCharacterSkills.vue new file mode 100644 index 0000000..5828138 --- /dev/null +++ b/frontend/components/molecules/dashboard/characters/DashboardCharacterSkills.vue @@ -0,0 +1,74 @@ + + + \ No newline at end of file diff --git a/frontend/components/molecules/dashboard/characters/DashboardCharacterStats.vue b/frontend/components/molecules/dashboard/characters/DashboardCharacterStats.vue new file mode 100644 index 0000000..7c9aa3c --- /dev/null +++ b/frontend/components/molecules/dashboard/characters/DashboardCharacterStats.vue @@ -0,0 +1,206 @@ + + + \ No newline at end of file diff --git a/frontend/components/molecules/dashboard/characters/DashboardFindCharacter.vue b/frontend/components/molecules/dashboard/characters/DashboardFindCharacter.vue new file mode 100644 index 0000000..5780171 --- /dev/null +++ b/frontend/components/molecules/dashboard/characters/DashboardFindCharacter.vue @@ -0,0 +1,59 @@ + + + \ No newline at end of file diff --git a/frontend/components/molecules/dashboard/home/DashboardPlayersStatus.vue b/frontend/components/molecules/dashboard/home/DashboardPlayersStatus.vue index 719cd81..ab3f353 100644 --- a/frontend/components/molecules/dashboard/home/DashboardPlayersStatus.vue +++ b/frontend/components/molecules/dashboard/home/DashboardPlayersStatus.vue @@ -1,7 +1,7 @@