diff --git a/README.md b/README.md index 0bfecb0..46347c5 100644 --- a/README.md +++ b/README.md @@ -7,3 +7,5 @@ This template should help get you started developing with Vue 3 and TypeScript i - [VS Code](https://code.visualstudio.com/) + [Vue - Official](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (previously Volar) and disable Vetur - Use [vue-tsc](https://github.com/vuejs/language-tools/tree/master/packages/tsc) for performing the same type checking from the command line, or for generating d.ts files for SFCs. + +Component Library - Vuetify 3 diff --git a/index.html b/index.html index dde16aa..4971f14 100644 --- a/index.html +++ b/index.html @@ -1,9 +1,14 @@ - + + + Vite + Vue + TS diff --git a/package.json b/package.json index df5cfb8..de88235 100644 --- a/package.json +++ b/package.json @@ -9,6 +9,9 @@ "preview": "vite preview" }, "dependencies": { + "@types/axios": "^0.14.0", + "@types/node": "^22.5.4", + "axios": "^1.7.7", "keycloak-js": "^25.0.2", "pinia": "^2.2.0", "sass": "^1.77.4", diff --git a/src/App.vue b/src/App.vue index 721d1af..ed28f79 100644 --- a/src/App.vue +++ b/src/App.vue @@ -1,30 +1,25 @@ - + diff --git a/src/components/sidebar/sidebar.component.vue b/src/components/sidebar/sidebar.component.vue index 114dea0..b530210 100644 --- a/src/components/sidebar/sidebar.component.vue +++ b/src/components/sidebar/sidebar.component.vue @@ -1,34 +1,30 @@ \ No newline at end of file + + {{ username }} + + + + + + + + + + + diff --git a/src/infra/auth/memory-ad.service.ts b/src/infra/auth/memory-ad.service.ts new file mode 100644 index 0000000..9412e22 --- /dev/null +++ b/src/infra/auth/memory-ad.service.ts @@ -0,0 +1,22 @@ +import { AuthStore } from '../../store/auth-store.interface'; +import { AuthAd } from './auth-ad'; + +export class MemoryAdService implements AuthAd { + constructor(private readonly storeService: AuthStore) {} + async connect(): Promise { + this.storeService.setToken('mock token'); + + this.storeService.setUsername('Geraldo Silva'); + this.storeService.setUserCode('123456'); + + return true; + } + async refreshToken(): Promise { + return 'true'; + } + async disconnect(): Promise {} + + isAuthenticated(): boolean { + return true; + } +} diff --git a/src/infra/dependecy-injection/dependency-injection.ts b/src/infra/dependecy-injection/dependency-injection.ts index f1feb0c..1058a64 100644 --- a/src/infra/dependecy-injection/dependency-injection.ts +++ b/src/infra/dependecy-injection/dependency-injection.ts @@ -3,19 +3,23 @@ import { App } from 'vue'; import { authStore } from '../../store/auth-store'; import { AuthStore } from '../../store/auth-store.interface'; import { AUTH_AD, AuthAd } from '../auth/auth-ad'; -import { KeycloakAdService } from '../auth/keycloak-ad.service'; +import { MemoryAdService } from '../auth/memory-ad.service'; +import { HTTP_CLIENT, HttpClient } from '../http/http-client'; +import { AxiosAdapter } from '../http/axios-adapter'; export class DependencyInjection { store: AuthStore; authService: AuthAd; + httpClient: HttpClient; constructor() { this.store = authStore(); - this.authService = new KeycloakAdService(this.store); + this.authService = new MemoryAdService(this.store); + this.httpClient = new AxiosAdapter(); } async execute(applicationVue: App) { - // TODO: Add more service here applicationVue.provide(AUTH_AD, this.authService); + applicationVue.provide(HTTP_CLIENT, this.httpClient); } } diff --git a/src/infra/http/axios-adapter.ts b/src/infra/http/axios-adapter.ts new file mode 100644 index 0000000..c2cc91a --- /dev/null +++ b/src/infra/http/axios-adapter.ts @@ -0,0 +1,28 @@ +import axios, { Axios } from 'axios'; +import { HttpClient } from './http-client'; + +export class AxiosAdapter implements HttpClient { + private http: Axios; + + constructor() { + this.http = axios.create({ + baseURL: import.meta.env.VITE_BACKEND_URL, + }); + } + + async get(url: string): Promise { + return this.http.get(url).then((response) => response.data); + } + + async post(url: string, data: any): Promise { + return this.http.post(url, data).then((response) => response.data); + } + + async put(url: string, data: any): Promise { + return this.http.put(url, data).then((response) => response.data); + } + + async delete(url: string): Promise { + return this.http.delete(url).then((response) => response.data); + } +} diff --git a/src/infra/http/http-client.ts b/src/infra/http/http-client.ts new file mode 100644 index 0000000..a08da4c --- /dev/null +++ b/src/infra/http/http-client.ts @@ -0,0 +1,7 @@ +export const HTTP_CLIENT = Symbol('HTTP_Client'); +export interface HttpClient { + get(url: string): Promise; + post(url: string, data: any): Promise; + put(url: string, data: any): Promise; + delete(url: string): Promise; +} diff --git a/src/modules/home/home.component.vue b/src/modules/home/home.component.vue index bccd8fc..ca87ba3 100644 --- a/src/modules/home/home.component.vue +++ b/src/modules/home/home.component.vue @@ -1,49 +1,50 @@ \ No newline at end of file + methods: { + createNewNationEvent() { + this.$router.push({ name: 'create-nation-event' }); + }, + }, +}); + diff --git a/src/modules/league/list/league-list.component.vue b/src/modules/league/list/league-list.component.vue new file mode 100644 index 0000000..e69de29 diff --git a/src/modules/league/route.ts b/src/modules/league/route.ts index 8a51e64..cbd098e 100644 --- a/src/modules/league/route.ts +++ b/src/modules/league/route.ts @@ -1,21 +1,23 @@ -const routers = [ +import type { RouteRecordRaw } from 'vue-router'; + +const routers: readonly RouteRecordRaw[] = [ { path: '/league', component: () => import('./league.component.vue'), children: [ { name: 'create-league', - path: '/create', + path: 'create', + component: () => import('./form/league-form.component.vue'), + }, + { + path: 'edit/:id', component: () => import('./form/league-form.component.vue'), }, - // { - // path: 'edit/:id', - // component: () => import('./form/edit-league.component.vue'), - // }, - // { - // path: 'list', - // component: () => import('./list/list-league.component.vue'), - // }, + { + path: 'list', + component: () => import('./list/league-list.component.vue'), + }, ], }, ]; diff --git a/src/modules/nation-event/entities/nation-event.ts b/src/modules/nation-event/entities/nation-event.ts new file mode 100644 index 0000000..261dea0 --- /dev/null +++ b/src/modules/nation-event/entities/nation-event.ts @@ -0,0 +1,31 @@ +export class NationEvent { + public id: string; + public name: string; + public season: string; + + constructor( + data: NationEventInput = { + id: '', + name: '', + season: '', + } + ) { + this.id = data.id; + this.name = data.name; + this.season = data.season; + } + + create() { + console.log(this, 'vai salvar isso no backend'); + } + + update() { + // Update the nation event + } +} + +export type NationEventInput = { + id: string; + name: string; + season: string; +}; diff --git a/src/modules/nation-event/form/nation-event-form.component.vue b/src/modules/nation-event/form/nation-event-form.component.vue new file mode 100644 index 0000000..6a5478f --- /dev/null +++ b/src/modules/nation-event/form/nation-event-form.component.vue @@ -0,0 +1,87 @@ + + + diff --git a/src/modules/nation-event/list/nation-event-list.component.vue b/src/modules/nation-event/list/nation-event-list.component.vue new file mode 100644 index 0000000..9a91641 --- /dev/null +++ b/src/modules/nation-event/list/nation-event-list.component.vue @@ -0,0 +1,92 @@ + + + diff --git a/src/modules/nation-event/nation-event.component.vue b/src/modules/nation-event/nation-event.component.vue new file mode 100644 index 0000000..a44ab87 --- /dev/null +++ b/src/modules/nation-event/nation-event.component.vue @@ -0,0 +1,3 @@ + diff --git a/src/modules/nation-event/route.ts b/src/modules/nation-event/route.ts new file mode 100644 index 0000000..bcfce18 --- /dev/null +++ b/src/modules/nation-event/route.ts @@ -0,0 +1,25 @@ +import type { RouteRecordRaw } from 'vue-router'; + +const routers: readonly RouteRecordRaw[] = [ + { + path: '/nation-events', + component: () => import('./nation-event.component.vue'), + children: [ + { + path: '', + component: () => import('./list/nation-event-list.component.vue'), + }, + { + name: 'create-nation-event', + path: 'cadastrar', + component: () => import('./form/nation-event-form.component.vue'), + }, + { + path: 'editar/:id', + component: () => import('./form/nation-event-form.component.vue'), + }, + ], + }, +]; + +export default routers; diff --git a/src/modules/nation-event/services/nation-event.service.ts b/src/modules/nation-event/services/nation-event.service.ts new file mode 100644 index 0000000..284ec01 --- /dev/null +++ b/src/modules/nation-event/services/nation-event.service.ts @@ -0,0 +1,51 @@ +import { HttpClient } from '../../../infra/http/http-client'; +import { NationEvent } from '../entities/nation-event'; + +export class NationEventService { + constructor(private readonly httpClient: HttpClient) {} + + getNationEvents() { + return this.httpClient.get( + '/nation-events' + ); + } + + createNationEvent(data: any) { + return this.httpClient.post('/nation-events', data); + } + + updateNationEvent(data: any) { + return this.httpClient.put(`/nation-events/${data.id}`, data); + } + + deleteNationEvent(id: string) { + return this.httpClient.delete(`/nation-events/${id}`); + } + + getNationEventById(id: string): Promise { + return this.httpClient + .get(`/nation-events/${id}`) + .then( + (data) => + new NationEvent({ + id: data.id, + name: data.name, + season: data.season, + }) + ); + } +} + +export type NationEventBackendResponse = { + id: string; + name: string; + season: string; +}; + +export type NationEventListBackendResponse = { + id: string; + name: string; + nationCount: number; + gamesCount: string; + season: string; +}[]; diff --git a/src/plugins/vuetify.ts b/src/plugins/vuetify.ts index 1fe315c..1e8bdb8 100644 --- a/src/plugins/vuetify.ts +++ b/src/plugins/vuetify.ts @@ -1,6 +1,7 @@ import { createVuetify } from 'vuetify'; import * as components from 'vuetify/components'; import * as directives from 'vuetify/directives'; + import 'vuetify/styles'; const rockstartTheme = { dark: true, @@ -22,6 +23,9 @@ const rockstartTheme = { }; const vuetify = createVuetify({ components, + icons: { + defaultSet: 'mdi', + }, directives, theme: { defaultTheme: 'rockstartTheme', diff --git a/src/routes/router.ts b/src/routes/router.ts index 482d011..78f5d98 100644 --- a/src/routes/router.ts +++ b/src/routes/router.ts @@ -1,9 +1,14 @@ -import { createRouter, createWebHistory } from 'vue-router'; +import { createRouter, createWebHistory, RouteRecordRaw } from 'vue-router'; import HomeView from '../modules/home/home.component.vue'; -import RouterModule from '../modules/league/route'; +import LeagueModule from '../modules/league/route'; +import NationEventModule from '../modules/nation-event/route'; -const routes = [{ path: '/', component: HomeView }, ...RouterModule]; +const routes: readonly RouteRecordRaw[] = [ + { path: '/', component: HomeView }, + ...LeagueModule, + ...NationEventModule, +]; export const router = createRouter({ history: createWebHistory(), diff --git a/src/style.css b/src/style.css index bb131d6..91d0926 100644 --- a/src/style.css +++ b/src/style.css @@ -3,7 +3,7 @@ line-height: 1.5; font-weight: 400; - color-scheme: light dark; + color-scheme: dark; color: rgba(255, 255, 255, 0.87); background-color: #242424; diff --git a/vite.config.ts b/vite.config.ts index 05c1740..bdab0ef 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -1,7 +1,16 @@ -import { defineConfig } from 'vite' -import vue from '@vitejs/plugin-vue' +import { defineConfig } from 'vite'; +import vue from '@vitejs/plugin-vue'; // https://vitejs.dev/config/ export default defineConfig({ plugins: [vue()], -}) + server: { + proxy: { + '/api': { + target: process.env.VITE_BACKEND_URL, + changeOrigin: true, + rewrite: (path) => path.replace(/^\/api/, ''), + }, + }, + }, +}); diff --git a/yarn.lock b/yarn.lock index a17f9f1..81745e5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -207,11 +207,25 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz#5d694d345ce36b6ecf657349e03eb87297e68da4" integrity sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g== +"@types/axios@^0.14.0": + version "0.14.0" + resolved "https://registry.yarnpkg.com/@types/axios/-/axios-0.14.0.tgz#ec2300fbe7d7dddd7eb9d3abf87999964cafce46" + integrity sha512-KqQnQbdYE54D7oa/UmYVMZKq7CO4l8DEENzOKc4aBRwxCXSlJXGz83flFx5L7AWrOQnmuN3kVsRdt+GZPPjiVQ== + dependencies: + axios "*" + "@types/estree@1.0.5": version "1.0.5" resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== +"@types/node@^22.5.4": + version "22.5.4" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.5.4.tgz#83f7d1f65bc2ed223bdbf57c7884f1d5a4fa84e8" + integrity sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg== + dependencies: + undici-types "~6.19.2" + "@vitejs/plugin-vue@^5.0.4": version "5.0.4" resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.0.4.tgz#508d6a0f2440f86945835d903fcc0d95d1bb8a37" @@ -349,6 +363,20 @@ anymatch@~3.1.2: normalize-path "^3.0.0" picomatch "^2.0.4" +asynckit@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" + integrity sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q== + +axios@*, axios@^1.7.7: + version "1.7.7" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.7.7.tgz#2f554296f9892a72ac8d8e4c5b79c14a91d0a47f" + integrity sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q== + dependencies: + follow-redirects "^1.15.6" + form-data "^4.0.0" + proxy-from-env "^1.1.0" + balanced-match@^1.0.0: version "1.0.2" resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" @@ -388,6 +416,13 @@ braces@~3.0.2: optionalDependencies: fsevents "~2.3.2" +combined-stream@^1.0.8: + version "1.0.8" + resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" + integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== + dependencies: + delayed-stream "~1.0.0" + computeds@^0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/computeds/-/computeds-0.0.1.tgz#215b08a4ba3e08a11ff6eee5d6d8d7166a97ce2e" @@ -403,6 +438,11 @@ de-indent@^1.0.2: resolved "https://registry.yarnpkg.com/de-indent/-/de-indent-1.0.2.tgz#b2038e846dc33baa5796128d0804b455b8c1e21d" integrity sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg== +delayed-stream@~1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" + integrity sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ== + entities@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48" @@ -449,6 +489,20 @@ fill-range@^7.1.1: dependencies: to-regex-range "^5.0.1" +follow-redirects@^1.15.6: + version "1.15.9" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.9.tgz#a604fa10e443bf98ca94228d9eebcc2e8a2c8ee1" + integrity sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ== + +form-data@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/form-data/-/form-data-4.0.0.tgz#93919daeaf361ee529584b9b31664dc12c9fa452" + integrity sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww== + dependencies: + asynckit "^0.4.0" + combined-stream "^1.0.8" + mime-types "^2.1.12" + fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" @@ -520,6 +574,18 @@ magic-string@^0.30.10: dependencies: "@jridgewell/sourcemap-codec" "^1.4.15" +mime-db@1.52.0: + version "1.52.0" + resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70" + integrity sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg== + +mime-types@^2.1.12: + version "2.1.35" + resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.35.tgz#381a871b62a734450660ae3deee44813f70d959a" + integrity sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw== + dependencies: + mime-db "1.52.0" + minimatch@^9.0.3: version "9.0.4" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.4.tgz#8e49c731d1749cbec05050ee5145147b32496a51" @@ -574,6 +640,11 @@ postcss@^8.4.38: picocolors "^1.0.0" source-map-js "^1.2.0" +proxy-from-env@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/proxy-from-env/-/proxy-from-env-1.1.0.tgz#e102f16ca355424865755d2c9e8ea4f24d58c3e2" + integrity sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg== + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -637,6 +708,11 @@ typescript@^5.2.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.4.5.tgz#42ccef2c571fdbd0f6718b1d1f5e6e5ef006f611" integrity sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ== +undici-types@~6.19.2: + version "6.19.8" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" + integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== + vite@^5.2.0: version "5.2.11" resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.11.tgz#726ec05555431735853417c3c0bfb36003ca0cbd"