commit 54fc9f400bf67c4e5e433a7fd27920715be184b9 Author: LeoMortari Date: Thu Aug 28 20:22:13 2025 -0300 init repo diff --git a/.env.development b/.env.development new file mode 100644 index 0000000..8d2d0c6 --- /dev/null +++ b/.env.development @@ -0,0 +1 @@ +VITE_ENV=development \ No newline at end of file diff --git a/.env.production b/.env.production new file mode 100644 index 0000000..b4d65a3 --- /dev/null +++ b/.env.production @@ -0,0 +1 @@ +VITE_ENV=production \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a855384 --- /dev/null +++ b/.gitignore @@ -0,0 +1,26 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local +yarn.lock +package-lock.json + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..a7cea0b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["Vue.volar"] +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..9a17c4d --- /dev/null +++ b/README.md @@ -0,0 +1,21 @@ +# Vue 3 + Vite ❤ + +Este projeto é uma base para aplicações front-end Vue 3, utilizando Vite para um desenvolvimento rápido e eficiente. Abaixo estão as bibliotecas mais importantes utilizadas neste projeto: + +## Dependências Principais + +- **Vue**: Um framework progressivo para a construção de interfaces de usuário. Ele é projetado para ser incrementalmente adotável, o que significa que você pode usá-lo para desenvolver desde pequenas partes de uma aplicação até grandes aplicações de página única. + +- **Quasar**: Um framework Vue.js de alto desempenho que permite construir websites responsivos, PWAs (Progressive Web Apps), aplicações SSR (Server-Side Rendered), SPAs (Single-Page Applications), aplicações móveis e aplicações desktop a partir de uma única base de código. + +- **Vue Router**: O roteador oficial para Vue.js. Ele se integra profundamente com o Vue.js para facilitar a construção de Single Page Applications robustas com roteamento dinâmico de componentes. + +- **Vuex**: A biblioteca oficial de gerenciamento de estado para aplicações Vue.js. Ele serve como um armazenamento centralizado para todos os componentes em uma aplicação, com regras que garantem que o estado só possa ser modificado de forma previsível. + +- **Axios**: Um cliente HTTP baseado em Promises para o navegador e Node.js. É amplamente utilizado para fazer requisições HTTP (GET, POST, PUT, DELETE, etc.) a APIs externas ou internas. + +- **Day.js**: Uma biblioteca JavaScript minimalista que analisa, valida, manipula e exibe datas e horas para navegadores modernos. Possui uma API amplamente compatível com Moment.js, mas com um tamanho de arquivo muito menor. + +- **Lodash**: Uma biblioteca utilitária JavaScript moderna que oferece modularidade, desempenho e recursos extras. Ela fornece funções para manipulação de arrays, objetos, strings, números e muito mais, tornando o código mais conciso e legível. + +- **@quasar/extras**: Fornece ativos extras para o Quasar, como ícones (Material Icons, Font Awesome, etc.) e fontes, que são essenciais para a estilização e a interface do usuário das aplicações Quasar. diff --git a/index.html b/index.html new file mode 100644 index 0000000..6d865b6 --- /dev/null +++ b/index.html @@ -0,0 +1,15 @@ + + + + + + + + + Vue Base JS + + +
+ + + diff --git a/package.json b/package.json new file mode 100644 index 0000000..a390630 --- /dev/null +++ b/package.json @@ -0,0 +1,33 @@ +{ + "name": "vue-frontend-base-js", + "private": true, + "version": "0.0.1", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "@quasar/extras": "1.17.0", + "@vee-validate/zod": "4.15.1", + "axios": "1.11.0", + "dayjs": "1.11.13", + "js-cookie": "3.0.5", + "lodash": "4.17.21", + "quasar": "2.18.2", + "vee-validate": "4.15.1", + "vue": "3.5.18", + "vue-router": "4.5.1", + "vuex": "4.1.0", + "zod": "4.1.5" + }, + "devDependencies": { + "@quasar/vite-plugin": "1.10.0", + "@types/js-cookie": "3.0.6", + "@types/lodash": "4.17.20", + "@vitejs/plugin-vue": "6.0.1", + "sass-embedded": "1.90.0", + "vite": "7.1.1" + } +} diff --git a/public/vite.svg b/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/App.vue b/src/App.vue new file mode 100644 index 0000000..d10e643 --- /dev/null +++ b/src/App.vue @@ -0,0 +1,78 @@ + + + + + diff --git a/src/assets/logo_clipperai.png b/src/assets/logo_clipperai.png new file mode 100644 index 0000000..10146ee Binary files /dev/null and b/src/assets/logo_clipperai.png differ diff --git a/src/assets/vue.svg b/src/assets/vue.svg new file mode 100644 index 0000000..770e9d3 --- /dev/null +++ b/src/assets/vue.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/auth/roles.js b/src/auth/roles.js new file mode 100644 index 0000000..8c8cc31 --- /dev/null +++ b/src/auth/roles.js @@ -0,0 +1,3 @@ +export default { + VIDEOS_LIST: "role_videos_6550", +}; diff --git a/src/auth/router.js b/src/auth/router.js new file mode 100644 index 0000000..a370db1 --- /dev/null +++ b/src/auth/router.js @@ -0,0 +1,100 @@ +import Cookies from "js-cookie"; + +import { createWebHistory, createRouter } from "vue-router"; + +import roles from "@/auth/roles"; + +import Videos from "@/routes/videos"; +import Login from "@/routes/auth/Login.vue"; + +const getUserRoles = () => { + const rolesFromCookie = Cookies.get("user_roles"); // TODO: Tirar as permissões do usuário + + return rolesFromCookie ? JSON.parse(rolesFromCookie) : []; +}; + +export const routes = [ + { + path: "/login", + name: "Login", + component: Login, + meta: { + guest: true, + title: "Login", + }, + }, + { + path: "/videos", + component: Videos, + name: "Videos", + meta: { + requiresAuth: true, + title: "Vídeos", + permissions: [roles.VIDEOS_LIST], + }, + }, + { + path: "/:pathMatch(.*)*", + redirect: (to) => { + return Cookies.get("token") ? "/videos" : "/login"; + }, + }, + { + path: "/", + redirect: (to) => { + console.log(Cookies); + return Cookies.get("token") ? "/videos" : "/login"; + }, + }, +]; + +export const router = createRouter({ + history: createWebHistory(), + routes, +}); + +export const isAuthenticated = () => { + return !!Cookies.get("token"); +}; + +const hasPermission = (requiredPermissions = []) => { + if (!requiredPermissions.length) return true; + + const userRoles = getUserRoles(); + + return requiredPermissions.some((permission) => + userRoles.includes(permission) + ); +}; + +router.beforeEach((to, from, next) => { + if (to.meta.title) { + document.title = `${to.meta.title} | ClipperIA`; + } + + if (to.matched.some((record) => record.meta.requiresAuth)) { + if (!isAuthenticated()) { + next({ + path: "/login", + query: { redirect: to.fullPath }, + }); + return; + } + + const requiredPermissions = to.meta.permissions || []; + + if (requiredPermissions.length > 0 && !hasPermission(requiredPermissions)) { + next({ path: "/unauthorized" }); + + return; + } + } + + if (to.matched.some((record) => record.meta.guest) && isAuthenticated()) { + next({ path: "/" }); + + return; + } + + next(); +}); diff --git a/src/components/Button/index.vue b/src/components/Button/index.vue new file mode 100644 index 0000000..ea5f0f8 --- /dev/null +++ b/src/components/Button/index.vue @@ -0,0 +1,50 @@ + + + diff --git a/src/components/Table/index.vue b/src/components/Table/index.vue new file mode 100644 index 0000000..d77621c --- /dev/null +++ b/src/components/Table/index.vue @@ -0,0 +1,92 @@ + + + diff --git a/src/components/TextField/index.vue b/src/components/TextField/index.vue new file mode 100644 index 0000000..de754e1 --- /dev/null +++ b/src/components/TextField/index.vue @@ -0,0 +1,31 @@ + + + diff --git a/src/components/Toggle/index.vue b/src/components/Toggle/index.vue new file mode 100644 index 0000000..1a3da08 --- /dev/null +++ b/src/components/Toggle/index.vue @@ -0,0 +1,30 @@ + + + diff --git a/src/main.js b/src/main.js new file mode 100644 index 0000000..4c447a6 --- /dev/null +++ b/src/main.js @@ -0,0 +1,30 @@ +import { createApp } from "vue"; +import { Quasar } from "quasar"; + +import quasarLang from "quasar/lang/pt-BR"; + +import "@quasar/extras/roboto-font/roboto-font.css"; +import "@quasar/extras/material-icons/material-icons.css"; +import "@quasar/extras/material-icons-outlined/material-icons-outlined.css"; +import "@quasar/extras/material-symbols-outlined/material-symbols-outlined.css"; +import "@quasar/extras/mdi-v7/mdi-v7.css"; + +import "quasar/src/css/index.sass"; + +import App from "./App.vue"; + +import { router } from "./auth/router"; + +const app = createApp(App); + +app.use(Quasar, { + config: { + dark: "auto", + }, + plugins: {}, + lang: quasarLang, +}); + +app.use(router); + +app.mount("#app"); diff --git a/src/quasar-variables.sass b/src/quasar-variables.sass new file mode 100644 index 0000000..637a8d1 --- /dev/null +++ b/src/quasar-variables.sass @@ -0,0 +1,11 @@ +$primary : #8200ff +$secondary : #eabdff +$accent : #8200ff + +$dark : #1c1e21 +$dark-page : #1c1e21 + +$success : #31cb00 +$error : #ee2e31 +$info : #226ce0 +$warning : #fcdc4d \ No newline at end of file diff --git a/src/routes/auth/Login.vue b/src/routes/auth/Login.vue new file mode 100644 index 0000000..7fb5253 --- /dev/null +++ b/src/routes/auth/Login.vue @@ -0,0 +1,166 @@ + + + + + diff --git a/src/routes/videos/index.vue b/src/routes/videos/index.vue new file mode 100644 index 0000000..c2d744c --- /dev/null +++ b/src/routes/videos/index.vue @@ -0,0 +1,192 @@ + + + + + diff --git a/vite.config.js b/vite.config.js new file mode 100644 index 0000000..9a46fcd --- /dev/null +++ b/vite.config.js @@ -0,0 +1,28 @@ +import vue from "@vitejs/plugin-vue"; +import path from "node:path"; + +import { defineConfig } from "vite"; +import { fileURLToPath } from "node:url"; +import { quasar, transformAssetUrls } from "@quasar/vite-plugin"; + +export default defineConfig({ + resolve: { + alias: { + "@": path.resolve(__dirname, "src/"), + "@assets": path.resolve(__dirname, "src/assets/"), + "@components": path.resolve(__dirname, "src/components/"), + "@utils": path.resolve(__dirname, "src/utils/"), + }, + extensions: [".js", ".vue", ".json"], + }, + plugins: [ + vue({ + template: { transformAssetUrls }, + }), + quasar({ + sassVariables: fileURLToPath( + new URL("./src/quasar-variables.sass", import.meta.url) + ), + }), + ], +});