diff --git a/.dockerignore b/.dockerignore
index c2923d8..ebe0776 100644
--- a/.dockerignore
+++ b/.dockerignore
@@ -8,3 +8,5 @@ CONTRIBUTING.md
LICENSE
README.md
SECURITY.md
+test-results
+playwright-report
diff --git a/.gitignore b/.gitignore
index ecfdb4f..d504dd4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -35,3 +35,5 @@ yarn.lock
pnpm-lock.yaml
*storybook.log
+test-results
+playwright-report
diff --git a/.storybook/main.ts b/.storybook/main.ts
index 5d43640..ab1922e 100644
--- a/.storybook/main.ts
+++ b/.storybook/main.ts
@@ -1,21 +1,19 @@
-import type {StorybookConfig} from "@storybook/vue3-vite";
+import type { StorybookConfig } from "@storybook/vue3-vite";
const config: StorybookConfig = {
- stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"],
- addons: [
- "@storybook/addon-onboarding",
- "@storybook/addon-links",
- "@storybook/addon-essentials",
- "@chromatic-com/storybook",
- "@storybook/addon-interactions",
- ],
- framework: {
- name: "@storybook/vue3-vite",
- options: {},
- },
- docs: {
- autodocs: "tag",
- },
- staticDirs: ["../public"],
+ stories: [ "../stories/**/*.stories.ts" ],
+ addons: [
+ "@storybook/addon-onboarding",
+ "@storybook/addon-links",
+ "@storybook/addon-essentials",
+ "@chromatic-com/storybook",
+ "@storybook/addon-interactions",
+ ],
+ framework: {
+ name: "@storybook/vue3-vite",
+ options: {},
+ },
+ docs: {},
+ staticDirs: [ "../public" ],
};
export default config;
diff --git a/.storybook/manager.ts b/.storybook/manager.ts
index b51ccfb..3d99cf9 100644
--- a/.storybook/manager.ts
+++ b/.storybook/manager.ts
@@ -5,7 +5,7 @@ addons.setConfig({
theme: create({
base: "dark",
textColor: "white",
- appPreviewBg: "#333333",
+ appPreviewBg: "#0f101d",
brandTitle: "NEI Market Analytics",
brandUrl: "https://bush1d3v-portfolio.vercel.app/",
brandImage: "logo.svg",
diff --git a/.storybook/preview.ts b/.storybook/preview.ts
index 208f92f..61b3760 100644
--- a/.storybook/preview.ts
+++ b/.storybook/preview.ts
@@ -20,7 +20,7 @@ const preview: Preview = {
values: [
{
name: "dark",
- value: "#333333",
+ value: "#0f101d",
},
{
name: "light",
@@ -29,8 +29,18 @@ const preview: Preview = {
],
},
},
- tags: ["autodocs"],
- decorators: [withActions],
+ tags: ["autodocs", "autodocs"],
+ decorators: [
+ withActions,
+ (story) => ({
+ components: {story},
+ template: `
+
+
+
+ `,
+ }),
+ ],
};
export default preview;
diff --git a/Dockerfile b/Dockerfile
index edd7213..025ebe7 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -2,7 +2,9 @@ FROM node:20
RUN apt-get update && apt-get install -y \
xdg-utils \
- git-all
+ git-all \
+ libevent-2.1-7 \
+ libgstreamer-plugins-bad1.0-0
WORKDIR /app
@@ -14,4 +16,6 @@ EXPOSE 5173
EXPOSE 6006
+EXPOSE 9323
+
CMD ["npm", "run", "dev"]
diff --git a/README.md b/README.md
index acb2a1d..1325fdc 100644
--- a/README.md
+++ b/README.md
@@ -27,7 +27,8 @@ O **NEI Market Analytics** é um projeto de código aberto projetado para fornec
-
+
+
@@ -73,7 +74,13 @@ bun build
### Executar testes de unidade com [Vitest](https://vitest.dev/)
```sh
-bun tests
+bun test:unit
+```
+
+### Executar testes de ponta a ponta com [Playwright](https://playwright.dev/)
+
+```sh
+bun test:e2e
```
Isso executa os testes de ponta a ponta no servidor de desenvolvimento Vite.
@@ -109,7 +116,8 @@ The **NEI Market Analytics** is an open-source project designed to provide compr
-
+
+
@@ -155,5 +163,11 @@ bun build
### Run Unit Tests with [Vitest](https://vitest.dev/)
```sh
-bun tests
+bun test:unit
+```
+
+### Run E2E Tests with [Playwright](https://playwright.dev/)
+
+```sh
+bun test:e2e
```
diff --git a/docker-compose.yml b/docker-compose.yml
index b9fa9b6..556dd41 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -6,10 +6,7 @@ services:
volumes:
- .:/app
working_dir: /app
- environment:
- - GIT_USER_EMAIL=${GIT_USER_EMAIL}
- - GIT_USER_NAME=${GIT_USER_NAME}
- command: sh -c "git config --global user.email \"$GIT_USER_EMAIL\" && git config --global user.name \"$GIT_USER_NAME\" && git config --global --add safe.directory /app && npm run dev"
+ command: npm run dev
ports:
- "5173:5173"
@@ -26,3 +23,14 @@ services:
- "6006:6006"
depends_on:
- vue
+
+ playwright:
+ image: node:20
+ volumes:
+ - .:/app
+ working_dir: /app
+ command: sh -c "npx playwright install-deps && npx playwright install chromium && npx playwright install firefox && apt-get install -y xvfb xauth && xvfb-run -- npx playwright test --ui"
+ ports:
+ - "9323:9323"
+ depends_on:
+ - vue
diff --git a/e2e/about-us.spec.ts b/e2e/about-us.spec.ts
new file mode 100644
index 0000000..86d06d5
--- /dev/null
+++ b/e2e/about-us.spec.ts
@@ -0,0 +1,45 @@
+import { test, expect } from "@playwright/test";
+
+test.describe("About Us Page Tests", () => {
+ test("Visits the about-us page and checks content", async ({ page }) => {
+ await page.goto("/about-us");
+
+ const mainContent = page.locator("main.container");
+ await expect(mainContent).toBeVisible();
+
+ const h1 = mainContent.locator("h1");
+ await expect(h1).toHaveText("Impulsionando o Futuro Juntos");
+
+ const h2 = mainContent.locator("h2");
+ await expect(h2).toHaveText("Colaborando para um amanhã mais tecnológico.");
+
+ const p = mainContent.locator("p");
+ await expect(p).toHaveText("Por Trás dos Códigos");
+
+ const header = page.locator("header");
+ await expect(header).toBeVisible();
+
+ const footer = page.locator("footer");
+ await expect(footer).toBeVisible();
+ });
+
+ test("Checks visibility of Accordion and Badges components", async ({ page }) => {
+ await page.goto("/about-us");
+
+ const accordion = page.locator("[data-testid='Accordion']");
+ await expect(accordion).toBeVisible();
+
+ const badges = page.locator("[data-testid='Badges']");
+ await expect(badges).toBeVisible();
+ });
+
+ // test("Checks navigation back to home", async ({ page }) => {
+ // await page.goto("/about-us");
+
+ // const homeLink = page.locator("a[href='/']");
+ // await expect(homeLink).toBeVisible();
+ // await homeLink.click();
+
+ // await expect(page).toHaveURL("/");
+ // });
+});
diff --git a/e2e/home.spec.ts b/e2e/home.spec.ts
new file mode 100644
index 0000000..b98ad8c
--- /dev/null
+++ b/e2e/home.spec.ts
@@ -0,0 +1,35 @@
+import { test, expect } from "@playwright/test";
+
+test.describe("Home Page Tests", () => {
+ test("Visits the app root url and checks main content", async ({ page }) => {
+ await page.goto("/");
+
+ const mainContainer = page.locator("main.container");
+ await expect(mainContainer).toBeVisible();
+ await expect(mainContainer).toHaveText("NEI Market Analytics");
+ });
+
+ test("Checks visibility of header", async ({ page }) => {
+ await page.goto("/");
+
+ const header = page.locator("header");
+ await expect(header).toBeVisible();
+ });
+
+ test("Checks visibility of footer", async ({ page }) => {
+ await page.goto("/");
+
+ const footer = page.locator("footer");
+ await expect(footer).toBeVisible();
+ });
+
+ test("Checks clickable text and navigation to about-us", async ({ page }) => {
+ await page.goto("/");
+
+ const clickableText = page.locator("main.container >> text=NEI Market Analytics");
+ await expect(clickableText).toBeVisible();
+ await clickableText.click();
+
+ await expect(page).toHaveURL("/about-us");
+ });
+});
diff --git a/e2e/tsconfig.json b/e2e/tsconfig.json
new file mode 100644
index 0000000..dfdb9af
--- /dev/null
+++ b/e2e/tsconfig.json
@@ -0,0 +1,4 @@
+{
+ "extends": "@tsconfig/node20/tsconfig.json",
+ "include": ["./**/*"]
+}
diff --git a/index.html b/index.html
index 85a6462..0a0c6c4 100644
--- a/index.html
+++ b/index.html
@@ -19,6 +19,11 @@
+
+
+
NEI Market Analytics
diff --git a/mocks/components/HoverCard.ts b/mocks/components/HoverCard.ts
new file mode 100644
index 0000000..d0adca1
--- /dev/null
+++ b/mocks/components/HoverCard.ts
@@ -0,0 +1,9 @@
+import type {HoverCardProps} from "@/components/HoverCard.vue";
+
+export const HoverCardMock: HoverCardProps = {
+ title: "John Doe",
+ description: "Creator of Radix UI and Figma's design system",
+ startDate: "February 2022",
+ avatarSrc: "https://avatars.githubusercontent.com/u/11473738?v=4",
+ avatarFallback: "JD",
+};
diff --git a/mocks/components/tags/Image.ts b/mocks/components/tags/Image.ts
new file mode 100644
index 0000000..5399308
--- /dev/null
+++ b/mocks/components/tags/Image.ts
@@ -0,0 +1,9 @@
+import type {ImageProps} from "@/tags/Image.vue";
+
+export const ImageMock: ImageProps = {
+ alt: "image",
+ height: "80",
+ width: "80",
+ src: "https://via.placeholder.com/80",
+ class: "w-20 h-20 rounded-full",
+};
diff --git a/mocks/components/tags/Link.ts b/mocks/components/tags/Link.ts
new file mode 100644
index 0000000..82619f2
--- /dev/null
+++ b/mocks/components/tags/Link.ts
@@ -0,0 +1,7 @@
+import type {LinkProps} from "@/tags/Link.vue";
+
+export const LinkMock: LinkProps = {
+ href: "https://www.google.com",
+ target: "_blank",
+ class: "font-bold underline",
+};
diff --git a/package.json b/package.json
index 6b69c37..70e823b 100644
--- a/package.json
+++ b/package.json
@@ -6,18 +6,21 @@
"license": "MIT",
"scripts": {
"dev": "vite",
- "build": "run-p type-check \"build-only {@}\" --",
+ "builds": "run-p type-check \"build-only {@}\" --",
"preview": "vite preview",
- "tests": "vitest",
+ "test:unit": "vitest",
+ "test:e2e": "playwright test",
+ "test:report": "bunx playwright show-report",
+ "test:e2e-ui": "bunx playwright test --ui",
"storybook": "storybook dev -p 6006",
"lint": "npx @biomejs/biome format --write ./",
"build-only": "vite build",
"type-check": "vue-tsc --build --force",
+ "build-storybook": "storybook build",
"docker-build": "docker-compose build",
"docker-run": "docker build -t nei_market_analytics .",
"docker-up": "docker-compose up",
- "docker-clean": "docker-compose down",
- "build-storybook": "storybook build"
+ "docker-clean": "docker-compose down"
},
"dependencies": {
"@radix-icons/vue": "^1.0.0",
@@ -33,18 +36,19 @@
"vue-router": "^4.3.3"
},
"devDependencies": {
+ "@playwright/test": "^1.44.1",
"@biomejs/biome": "^1.8.3",
- "@chromatic-com/storybook": "^1.9.0",
- "@storybook/addon-essentials": "^8.2.9",
- "@storybook/addon-interactions": "^8.2.9",
- "@storybook/addon-links": "^8.2.9",
- "@storybook/addon-onboarding": "^8.2.9",
- "@storybook/blocks": "^8.2.9",
- "@storybook/manager-api": "^8.2.9",
- "@storybook/test": "^8.2.9",
- "@storybook/theming": "^8.2.9",
- "@storybook/vue3": "^8.2.9",
- "@storybook/vue3-vite": "^8.2.9",
+ "@chromatic-com/storybook": "^2.0.2",
+ "@storybook/addon-essentials": "^8.3.0",
+ "@storybook/addon-interactions": "^8.3.0",
+ "@storybook/addon-links": "^8.3.0",
+ "@storybook/addon-onboarding": "^8.3.0",
+ "@storybook/blocks": "^8.3.0",
+ "@storybook/manager-api": "^8.3.0",
+ "@storybook/test": "^8.3.0",
+ "@storybook/theming": "^8.3.0",
+ "@storybook/vue3": "^8.3.0",
+ "@storybook/vue3-vite": "^8.3.0",
"@testing-library/vue": "^8.1.0",
"@tsconfig/node20": "^20.1.4",
"@types/jsdom": "^21.1.7",
@@ -56,9 +60,8 @@
"autoprefixer": "^10.4.20",
"jsdom": "^25.0.0",
"npm-run-all2": "^6.2.0",
- "shadcn-nuxt": "^0.10.4",
"start-server-and-test": "^2.0.4",
- "storybook": "^8.2.9",
+ "storybook": "^8.3.0",
"typescript": "~5.5.4",
"vite": "^5.3.1",
"vite-plugin-vue-devtools": "^7.3.1",
diff --git a/playwright.config.ts b/playwright.config.ts
new file mode 100644
index 0000000..29d34c6
--- /dev/null
+++ b/playwright.config.ts
@@ -0,0 +1,86 @@
+import process from "node:process";
+import { defineConfig, devices } from "@playwright/test";
+
+/**
+ * Read environment variables from file.
+ * https://github.com/motdotla/dotenv
+ */
+// require('dotenv').config();
+
+/**
+ * See https://playwright.dev/docs/test-configuration.
+ */
+export default defineConfig({
+ testDir: "./e2e",
+ /* Maximum time one test can run for. */
+ timeout: 30 * 1000,
+ expect: {
+ /**
+ * Maximum time expect() should wait for the condition to be met.
+ * For example in `await expect(locator).toHaveText();`
+ */
+ timeout: 5000,
+ },
+ /* Fail the build on CI if you accidentally left test.only in the source code. */
+ forbidOnly: !!process.env.CI,
+ /* Retry on CI only */
+ retries: process.env.CI ? 2 : 0,
+ /* Opt out of parallel tests on CI. */
+ workers: process.env.CI ? 1 : undefined,
+ /* Reporter to use. See https://playwright.dev/docs/test-reporters */
+ reporter: [ [ 'html', { outputFolder: 'playwright-report' } ] ],
+ /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */
+ use: {
+ /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */
+ actionTimeout: 0,
+ /* Base URL to use in actions like `await page.goto('/')`. */
+ baseURL: "http://localhost:5173",
+
+ /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */
+ trace: "on-first-retry",
+
+ /* Only on CI systems run the tests headless */
+ headless: !!process.env.CI,
+
+ /* Take a screenshot on failure */
+ screenshot: 'only-on-failure',
+ video: 'retain-on-failure',
+ },
+
+ /* Configure projects for major browsers */
+ projects: [
+ {
+ name: "chromium",
+ use: {
+ ...devices[ "Desktop Chrome" ],
+ },
+ },
+ {
+ name: "firefox",
+ use: {
+ ...devices[ "Desktop Firefox" ],
+ },
+ },
+ {
+ name: "Mobile Chrome",
+ use: {
+ ...devices[ "Pixel 5" ],
+ },
+ },
+ ],
+
+ /* Folder for test artifacts such as screenshots, videos, traces, etc. */
+ // outputDir: 'test-results/',
+
+ /* Run your local dev server before starting the tests */
+ webServer: {
+ /**
+ * Use the dev server by default for faster feedback loop.
+ * Use the preview server on CI for more realistic testing.
+ * Playwright will re-use the local server if there is already a dev-server running.
+ */
+ command: process.env.CI ? "vite preview --port 5173" : "vite dev",
+ port: 5173,
+ reuseExistingServer: !process.env.CI,
+ },
+});
diff --git a/public/sitemap.xml b/public/sitemap.xml
index 2595c3e..6e70dba 100644
--- a/public/sitemap.xml
+++ b/public/sitemap.xml
@@ -7,7 +7,7 @@
1.0
- http://localhost:5173/about
+ http://localhost:5173/about-us
2023-10-01
monthly
0.8
diff --git a/src/App.vue b/src/App.vue
index 6d7b1b5..936445c 100644
--- a/src/App.vue
+++ b/src/App.vue
@@ -1,6 +1,7 @@
diff --git a/src/assets/css/main.css b/src/assets/css/main.css
index db0c694..796db78 100644
--- a/src/assets/css/main.css
+++ b/src/assets/css/main.css
@@ -4,25 +4,25 @@
@layer base {
:root {
- --foreground: rgb(245, 106, 36);
+ --foreground: #ffffff;
--muted: rgb(12, 12, 12);
--muted-foreground: rgb(141, 67, 14);
--popover: rgb(0, 0, 0);
- --popover-foreground: rgb(245, 106, 36);
+ --popover-foreground: #ffffff;
--card: rgb(0, 0, 0);
- --card-foreground: rgb(245, 106, 36);
+ --card-foreground: #ffffff;
- --border: rgb(25, 19, 15);
--input: rgb(25, 19, 15);
+ --dark: #1e293b;
--text: #ffffff;
+ --text-foreground: #eeeeee;
--primary: #157efb;
--primary-foreground: #ffffff;
--secondary: #0088cc;
- --secondary-foreground: #eeeeee;
--surface: #17192e;
--material: #252d4a;
--texture: #161727;
@@ -36,7 +36,7 @@
--fg: #ffffff;
--fg-dim: #BAC8D2;
--fg-muted: #8b94a3;
- --secondary-lighter: #333f67;
+ --border: #222a44;
--secondary-darker: #171b2d;
--surface-lighter: #20223f;
--surface-darker: #0e101d;
@@ -60,73 +60,43 @@
--primary-darker: #ef233c;
--primary-darker: #edf2f4;
- --accent: rgb(12, 12, 12);
- --accent-foreground: rgb(230, 107, 25);
+ --accent: #2d375b;
+ --accent-foreground: #ffffff;
--destructive: rgb(149, 149, 149);
--destructive-foreground: rgb(22, 22, 22);
- --ring: rgb(245, 106, 36);
+ --ring: #ffffff;
--radius: 0.5rem;
}
-
- .dark {
- --background: rgb(245, 106, 36);
- --foreground: rgb(22, 22, 22);
-
- --muted: rgb(216, 57, 17);
- --muted-foreground: rgb(92, 45, 14);
-
- --popover: rgb(245, 106, 36);
- --popover-foreground: rgb(22, 22, 22);
-
- --card: rgb(245, 106, 36);
- --card-foreground: rgb(22, 22, 22);
-
- --border: rgb(216, 57, 17);
- --input: rgb(216, 57, 17);
-
- --primary: rgb(22, 22, 22);
- --primary-foreground: rgb(230, 107, 25);
-
- --secondary: rgb(216, 57, 17);
- --secondary-foreground: rgb(22, 22, 22);
-
- --accent: rgb(216, 57, 17);
- --accent-foreground: rgb(22, 22, 22);
-
- --destructive: rgb(177, 160, 160);
- --destructive-foreground: rgb(22, 22, 22);
-
- --ring: rgb(44, 26, 15);
- }
}
@layer base {
* {
@apply border-border p-0 m-0 box-border;
+ font-family: "Roboto", ui-sans-serif, system-ui, -apple-system, sans-serif;
}
body {
@apply min-h-screen bg-background text-text;
}
h1 {
- @apply text-4xl font-bold;
+ @apply text-3xl md:text-4xl lg:text-5xl font-bold;
}
h2 {
- @apply text-3xl font-bold;
+ @apply text-2xl md:text-3xl lg:text-4xl font-semibold;
}
h3 {
- @apply text-2xl font-bold;
+ @apply text-xl md:text-2xl lg:text-3xl font-semibold;
}
}
.container {
- @apply flex flex-col justify-center items-center min-h-[84dvh];
+ @apply flex flex-col items-center min-h-[80dvh] py-[3dvh] md:py-0 md:min-h-[84dvh] px-4 md:px-8;
}
.layout {
- @apply bg-surface min-h-[8dvh];
+ @apply bg-transparent min-h-[8dvh];
}
::-webkit-scrollbar {
diff --git a/src/components/Accordion.vue b/src/components/Accordion.vue
new file mode 100644
index 0000000..6b8bbcd
--- /dev/null
+++ b/src/components/Accordion.vue
@@ -0,0 +1,54 @@
+
+
+
+
+
+ {{ item.title }}
+
+ {{ item.content }}
+
+
+
+
diff --git a/src/components/Badges.vue b/src/components/Badges.vue
new file mode 100644
index 0000000..f31e0c6
--- /dev/null
+++ b/src/components/Badges.vue
@@ -0,0 +1,63 @@
+
+
+
+
+ -
+
+
+
+
+
+
+
+
+
+
+
{{ badge.name }}
+ {{ badge.occupation }}
+
+
+
+
+
+
diff --git a/src/components/Dropdown.vue b/src/components/Dropdown.vue
new file mode 100644
index 0000000..c7f9fc1
--- /dev/null
+++ b/src/components/Dropdown.vue
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+ Tópicos
+
+
+
+
+ Cripto moedas
+
+
+
+
+ Bitcoin
+
+
+ Ethereum
+
+
+ Dogecoin
+
+
+
+
+
+ Skins CS:GO
+ ⌘B
+
+
+ Moedas Globais
+ ⌘S
+
+
+
+
+
diff --git a/src/components/Dto/AccordionDto.ts b/src/components/Dto/AccordionDto.ts
new file mode 100644
index 0000000..a607a3d
--- /dev/null
+++ b/src/components/Dto/AccordionDto.ts
@@ -0,0 +1,22 @@
+import type {AccordionProps} from "@/components/Accordion.vue";
+
+export const AccordionDto: AccordionProps[] = [
+ {
+ value: "item-1",
+ title: "O que é o NEI Market Analytics?",
+ content:
+ "O NEI Market Analytics é um projeto de pesquisa e desenvolvimento open-source para auxiliar diversos nichos de investimento, como criptomoedas, moedas globais e skins de jogos.",
+ },
+ {
+ value: "item-2",
+ title: "O que preciso fazer para participar?",
+ content:
+ "Basta acessar! Você pode acessar tudo, sem restrições. Se quiser participar ainda mais compartilhando ideias, dúvidas ou respostas, basta criar sua conta!",
+ },
+ {
+ value: "item-3",
+ title: "Onde reporto um possível erro crítico?",
+ content:
+ "Em breve teremos um local mais apropriado para isso, porém, se sinta livre para compartilhar conosco sua descoberta pelo discord: bushi.021",
+ },
+];
diff --git a/src/components/Dto/BadgesDto.ts b/src/components/Dto/BadgesDto.ts
new file mode 100644
index 0000000..5e2b672
--- /dev/null
+++ b/src/components/Dto/BadgesDto.ts
@@ -0,0 +1,31 @@
+import type {BadgeProps} from "@/components/Badges.vue";
+
+export const BadgesDto: BadgeProps[] = [
+ {
+ name: "Victor Navarro",
+ occupation: "Software Engineer",
+ github: "https://github.com/bush1D3v",
+ nickname: "bush1D3v",
+ description: "Software Engineer | Vue.js | Rust | TypeScript | PHP | Docker | CI/CD",
+ startDate: "February 2023",
+ initialLetters: "VN",
+ },
+ {
+ name: "Erackson Souza",
+ occupation: "Frontend Developer",
+ github: "https://github.com/eracksonsouza",
+ nickname: "eracksonsouza",
+ description: "Web Developer | HTML | CSS | GIT | JavaScript | React | TypeScrip",
+ startDate: "February 2024",
+ initialLetters: "ES",
+ },
+ {
+ name: "Israel Pina",
+ occupation: "FullStack Developer",
+ github: "https://github.com/IsraelPina32",
+ nickname: "IsraelPina32",
+ description: "Software Engineer | Typescript | React | Tailwind | Next.js | Node.js",
+ startDate: "January 2022",
+ initialLetters: "IP",
+ },
+];
diff --git a/src/components/HoverCard.vue b/src/components/HoverCard.vue
new file mode 100644
index 0000000..ac91b89
--- /dev/null
+++ b/src/components/HoverCard.vue
@@ -0,0 +1,49 @@
+
+
+
+
+
+
+
+
+
+
+
+ {{ props.avatarFallback }}
+
+
+
+ @{{ props.title }}
+
+
+ {{ props.description }}
+
+
+
+
+ Joined {{ props.startDate }}
+
+
+
+
+
+
+
diff --git a/src/components/Layout/Footer.vue b/src/components/Layout/Footer.vue
new file mode 100644
index 0000000..119264b
--- /dev/null
+++ b/src/components/Layout/Footer.vue
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/src/components/Layout/Footer/Footer.vue b/src/components/Layout/Footer/Footer.vue
deleted file mode 100644
index 95856f1..0000000
--- a/src/components/Layout/Footer/Footer.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/src/components/Layout/Header.vue b/src/components/Layout/Header.vue
new file mode 100644
index 0000000..7d650c2
--- /dev/null
+++ b/src/components/Layout/Header.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
diff --git a/src/components/Layout/Header/Header.vue b/src/components/Layout/Header/Header.vue
deleted file mode 100644
index 59f286f..0000000
--- a/src/components/Layout/Header/Header.vue
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
diff --git a/src/components/Layout/index.ts b/src/components/Layout/index.ts
deleted file mode 100644
index 51af172..0000000
--- a/src/components/Layout/index.ts
+++ /dev/null
@@ -1,4 +0,0 @@
-import Header from "./Header/Header.vue";
-import Footer from "./Footer/Footer.vue";
-
-export {Header, Footer};
diff --git a/src/components/SearchBar.vue b/src/components/SearchBar.vue
new file mode 100644
index 0000000..b3e0b50
--- /dev/null
+++ b/src/components/SearchBar.vue
@@ -0,0 +1,168 @@
+
+
+
+
+
+
+
+
+ ⌘J
+
+
+
+
+
+
+
+
+ history
+ {{ item }}
+
+
+
+ Nenhum resultado encontrado.
+
+
+
+ Criar
+
+
+ table_view
+ Seus Lembretes
+
+
+
+
+ settings
+ Configurações
+
+
+ home
+ Página Inicial
+
+
+ table_view
+ Seus Lembretes
+
+
+ view_kanban
+ Gráficos
+
+
+ add
+ Criar
+
+
+
+ Raiva
+
+
+
+ Ansiedade
+
+
+
+ Tristeza
+
+
+
+ Inveja
+
+
+
+ Nojinho
+
+
+
+ Tédio
+
+
+
+ Alegria
+
+
+
+ Medo
+
+
+
+ Vergonha
+
+
+
+
+
+
diff --git a/src/components/Svg/ImageSkeletonSvg.vue b/src/components/Svg/ImageSkeletonSvg.vue
new file mode 100644
index 0000000..e1cd1dc
--- /dev/null
+++ b/src/components/Svg/ImageSkeletonSvg.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
diff --git a/src/components/ui/accordion/Accordion.vue b/src/components/ui/accordion/Accordion.vue
new file mode 100644
index 0000000..23b9266
--- /dev/null
+++ b/src/components/ui/accordion/Accordion.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/accordion/AccordionContent.vue b/src/components/ui/accordion/AccordionContent.vue
new file mode 100644
index 0000000..dbb18a0
--- /dev/null
+++ b/src/components/ui/accordion/AccordionContent.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/accordion/AccordionItem.vue b/src/components/ui/accordion/AccordionItem.vue
new file mode 100644
index 0000000..294fc5e
--- /dev/null
+++ b/src/components/ui/accordion/AccordionItem.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/accordion/AccordionTrigger.vue b/src/components/ui/accordion/AccordionTrigger.vue
new file mode 100644
index 0000000..c91a4cf
--- /dev/null
+++ b/src/components/ui/accordion/AccordionTrigger.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/accordion/index.ts b/src/components/ui/accordion/index.ts
new file mode 100644
index 0000000..ec0da08
--- /dev/null
+++ b/src/components/ui/accordion/index.ts
@@ -0,0 +1,4 @@
+export {default as Accordion} from "./Accordion.vue";
+export {default as AccordionContent} from "./AccordionContent.vue";
+export {default as AccordionItem} from "./AccordionItem.vue";
+export {default as AccordionTrigger} from "./AccordionTrigger.vue";
diff --git a/src/components/ui/avatar/Avatar.vue b/src/components/ui/avatar/Avatar.vue
new file mode 100644
index 0000000..3f8b234
--- /dev/null
+++ b/src/components/ui/avatar/Avatar.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/avatar/AvatarFallback.vue b/src/components/ui/avatar/AvatarFallback.vue
new file mode 100644
index 0000000..645087e
--- /dev/null
+++ b/src/components/ui/avatar/AvatarFallback.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/avatar/AvatarImage.vue b/src/components/ui/avatar/AvatarImage.vue
new file mode 100644
index 0000000..77f349f
--- /dev/null
+++ b/src/components/ui/avatar/AvatarImage.vue
@@ -0,0 +1,9 @@
+
+
+
+
+
diff --git a/src/components/ui/avatar/index.ts b/src/components/ui/avatar/index.ts
new file mode 100644
index 0000000..0b02ffe
--- /dev/null
+++ b/src/components/ui/avatar/index.ts
@@ -0,0 +1,24 @@
+import {type VariantProps, cva} from "class-variance-authority";
+
+export {default as Avatar} from "./Avatar.vue";
+export {default as AvatarImage} from "./AvatarImage.vue";
+export {default as AvatarFallback} from "./AvatarFallback.vue";
+
+export const avatarVariant = cva(
+ "inline-flex items-center justify-center font-normal text-foreground select-none shrink-0 bg-secondary overflow-hidden",
+ {
+ variants: {
+ size: {
+ sm: "h-10 w-10 text-xs",
+ base: "h-16 w-16 text-2xl",
+ lg: "h-32 w-32 text-5xl",
+ },
+ shape: {
+ circle: "rounded-full",
+ square: "rounded-md",
+ },
+ },
+ },
+);
+
+export type AvatarVariants = VariantProps;
diff --git a/src/components/ui/button/Button.spec.ts b/src/components/ui/button/Button.spec.ts
deleted file mode 100644
index 7f772d8..0000000
--- a/src/components/ui/button/Button.spec.ts
+++ /dev/null
@@ -1,24 +0,0 @@
-import {test, expect, describe, beforeEach} from "vitest";
-import {render, screen} from "@testing-library/vue";
-import Button from "./Button.vue";
-
-const buttonTestId: string = "ButtonSCN";
-
-describe("Shadcn-vue Button Component Tests", () => {
- beforeEach(() => {
- render(Button);
- });
-
- test("Should be able to render the component correctly", async () => {
- expect(screen.getByTestId(buttonTestId)).toBeDefined();
- });
-
- test("Should be able to render the component correctly with custom props", async () => {
- render(Button, {
- props: {
- default: "Button",
- },
- });
- expect(screen.getByText("Button")).toBeDefined();
- });
-});
diff --git a/src/components/ui/button/Button.stories.ts b/src/components/ui/button/Button.stories.ts
deleted file mode 100644
index e8f51b3..0000000
--- a/src/components/ui/button/Button.stories.ts
+++ /dev/null
@@ -1,85 +0,0 @@
-import type {Meta, StoryObj} from "@storybook/vue3";
-import {userEvent, within, expect} from "@storybook/test";
-import Button from "./Button.vue";
-
-const meta: Meta = {
- title: "Components/Shadcn/Button",
- component: Button,
- tags: ["autodocs"],
- parameters: {
- actions: {
- argTypesRegex: "^on.*",
- },
- },
- argTypes: {
- default: {
- description: "The content of the button.",
- control: {type: "text"},
- },
- variant: {
- description: "The variant of the button.",
- control: {type: "select"},
- options: ["default", "destructive", "outline", "secondary", "ghost", "link"],
- },
- size: {
- description: "The size of the button.",
- control: {type: "select"},
- options: ["default", "xs", "sm", "lg", "icon"],
- },
- class: {
- description: "Additional Tailwind classes for the button.",
- control: {type: "text"},
- },
- style: {
- description: "Additional CSS styles for the button.",
- control: {type: "text"},
- },
- as: {
- description: "The HTML tag to use for the button.",
- control: {type: "text"},
- },
- asChild: {
- description: "Whether to render the button as a child of another element.",
- control: {type: "boolean"},
- },
- },
-};
-
-export default meta;
-
-type Story = StoryObj;
-
-export const Default: Story = {
- name: "Default",
- args: {
- default: "Button",
- variant: "default",
- size: "default",
- class: "bg-red-500",
- as: "button",
- style: "",
- asChild: false,
- },
- play: async ({canvasElement, step}) => {
- const canvas = within(canvasElement);
-
- const buttonElement = canvas.getByTestId("ButtonSCN");
- await step("Render the button", async () => {
- expect(buttonElement).toBeDefined();
- });
-
- const buttonStyle = getComputedStyle(buttonElement);
- await step("Verify the initial button style", async () => {
- expect(buttonStyle.backgroundColor).toBe("rgb(239, 68, 68)");
- expect(buttonStyle.color).toBe("rgb(250, 250, 249)");
- });
-
- await step("Click the button", async () => {
- await userEvent.click(buttonElement);
- });
-
- await step("Hover the button", async () => {
- await userEvent.hover(buttonElement);
- });
- },
-};
diff --git a/src/components/ui/button/Button.vue b/src/components/ui/button/Button.vue
index 9809d74..0741a99 100644
--- a/src/components/ui/button/Button.vue
+++ b/src/components/ui/button/Button.vue
@@ -17,13 +17,8 @@ const props = withDefaults(defineProps(), {
-
-
- {{ props.default }}
-
+
+
+ {{ props.default }}
+
diff --git a/src/components/ui/button/index.ts b/src/components/ui/button/index.ts
index c6de83a..05bdfc7 100644
--- a/src/components/ui/button/index.ts
+++ b/src/components/ui/button/index.ts
@@ -1,34 +1,34 @@
-import {type VariantProps, cva} from "class-variance-authority";
+import { type VariantProps, cva } from "class-variance-authority";
-export {default as Button} from "./Button.vue";
+export { default as Button } from "./Button.vue";
export const buttonVariants = cva(
- "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
- {
- variants: {
- variant: {
- default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
- destructive:
- "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
- outline:
- "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
- secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
- ghost: "hover:bg-accent hover:text-accent-foreground",
- link: "text-primary underline-offset-4 hover:underline",
- },
- size: {
- default: "h-9 px-4 py-2",
- xs: "h-7 rounded px-2",
- sm: "h-8 rounded-md px-3 text-xs",
- lg: "h-10 rounded-md px-8",
- icon: "h-9 w-9",
- },
- },
- defaultVariants: {
- variant: "default",
- size: "default",
- },
- },
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
+ {
+ variants: {
+ variant: {
+ default: "bg-primary text-primary-foreground shadow hover:bg-accent",
+ destructive:
+ "bg-destructive text-destructive-foreground shadow-sm hover:bg-accent",
+ outline:
+ "border bg-background shadow-sm hover:bg-accent hover:text-textForeground",
+ secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-accent",
+ ghost: "hover:bg-accent hover:text-textForeground",
+ link: "text-primary underline-offset-4 hover:underline",
+ },
+ size: {
+ default: "h-9 px-4 py-2",
+ xs: "h-7 rounded px-2",
+ sm: "h-8 rounded-md px-3 text-xs",
+ lg: "h-10 rounded-md px-8",
+ icon: "h-9 w-9",
+ },
+ },
+ defaultVariants: {
+ variant: "default",
+ size: "default",
+ },
+ },
);
export type ButtonVariants = VariantProps;
diff --git a/src/components/ui/command/Command.vue b/src/components/ui/command/Command.vue
new file mode 100644
index 0000000..ad51b2d
--- /dev/null
+++ b/src/components/ui/command/Command.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/command/CommandDialog.vue b/src/components/ui/command/CommandDialog.vue
new file mode 100644
index 0000000..3df4a53
--- /dev/null
+++ b/src/components/ui/command/CommandDialog.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
diff --git a/src/components/ui/command/CommandEmpty.vue b/src/components/ui/command/CommandEmpty.vue
new file mode 100644
index 0000000..1295d2a
--- /dev/null
+++ b/src/components/ui/command/CommandEmpty.vue
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/command/CommandGroup.vue b/src/components/ui/command/CommandGroup.vue
new file mode 100644
index 0000000..0d36228
--- /dev/null
+++ b/src/components/ui/command/CommandGroup.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
+ {{ heading }}
+
+
+
+
diff --git a/src/components/ui/command/CommandInput.vue b/src/components/ui/command/CommandInput.vue
new file mode 100644
index 0000000..3d902f9
--- /dev/null
+++ b/src/components/ui/command/CommandInput.vue
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/command/CommandItem.vue b/src/components/ui/command/CommandItem.vue
new file mode 100644
index 0000000..5c6a6ff
--- /dev/null
+++ b/src/components/ui/command/CommandItem.vue
@@ -0,0 +1,26 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/command/CommandList.vue b/src/components/ui/command/CommandList.vue
new file mode 100644
index 0000000..00d1b3a
--- /dev/null
+++ b/src/components/ui/command/CommandList.vue
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/command/CommandSeparator.vue b/src/components/ui/command/CommandSeparator.vue
new file mode 100644
index 0000000..477799c
--- /dev/null
+++ b/src/components/ui/command/CommandSeparator.vue
@@ -0,0 +1,23 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/command/CommandShortcut.vue b/src/components/ui/command/CommandShortcut.vue
new file mode 100644
index 0000000..0d4da92
--- /dev/null
+++ b/src/components/ui/command/CommandShortcut.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/command/index.ts b/src/components/ui/command/index.ts
new file mode 100644
index 0000000..0e35f4b
--- /dev/null
+++ b/src/components/ui/command/index.ts
@@ -0,0 +1,9 @@
+export { default as Command } from './Command.vue'
+export { default as CommandDialog } from './CommandDialog.vue'
+export { default as CommandEmpty } from './CommandEmpty.vue'
+export { default as CommandGroup } from './CommandGroup.vue'
+export { default as CommandInput } from './CommandInput.vue'
+export { default as CommandItem } from './CommandItem.vue'
+export { default as CommandList } from './CommandList.vue'
+export { default as CommandSeparator } from './CommandSeparator.vue'
+export { default as CommandShortcut } from './CommandShortcut.vue'
diff --git a/src/components/ui/dialog/Dialog.vue b/src/components/ui/dialog/Dialog.vue
new file mode 100644
index 0000000..a04c026
--- /dev/null
+++ b/src/components/ui/dialog/Dialog.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogClose.vue b/src/components/ui/dialog/DialogClose.vue
new file mode 100644
index 0000000..a64703e
--- /dev/null
+++ b/src/components/ui/dialog/DialogClose.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogContent.vue b/src/components/ui/dialog/DialogContent.vue
new file mode 100644
index 0000000..78e83f6
--- /dev/null
+++ b/src/components/ui/dialog/DialogContent.vue
@@ -0,0 +1,44 @@
+
+
+
+
+
+
+
+
+
+
+ Close
+
+
+
+
diff --git a/src/components/ui/dialog/DialogDescription.vue b/src/components/ui/dialog/DialogDescription.vue
new file mode 100644
index 0000000..3637b7e
--- /dev/null
+++ b/src/components/ui/dialog/DialogDescription.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogFooter.vue b/src/components/ui/dialog/DialogFooter.vue
new file mode 100644
index 0000000..ac2d0c1
--- /dev/null
+++ b/src/components/ui/dialog/DialogFooter.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogHeader.vue b/src/components/ui/dialog/DialogHeader.vue
new file mode 100644
index 0000000..b2c9085
--- /dev/null
+++ b/src/components/ui/dialog/DialogHeader.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogScrollContent.vue b/src/components/ui/dialog/DialogScrollContent.vue
new file mode 100644
index 0000000..c959fd4
--- /dev/null
+++ b/src/components/ui/dialog/DialogScrollContent.vue
@@ -0,0 +1,51 @@
+
+
+
+
+
+ {
+ const originalEvent = event.detail.originalEvent;
+ const target = originalEvent.target as HTMLElement;
+ if (originalEvent.offsetX > target.clientWidth || originalEvent.offsetY > target.clientHeight) {
+ event.preventDefault();
+ }
+ }">
+
+
+
+
+ Close
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogTitle.vue b/src/components/ui/dialog/DialogTitle.vue
new file mode 100644
index 0000000..1bb4046
--- /dev/null
+++ b/src/components/ui/dialog/DialogTitle.vue
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/DialogTrigger.vue b/src/components/ui/dialog/DialogTrigger.vue
new file mode 100644
index 0000000..ee0c12f
--- /dev/null
+++ b/src/components/ui/dialog/DialogTrigger.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dialog/index.ts b/src/components/ui/dialog/index.ts
new file mode 100644
index 0000000..847e999
--- /dev/null
+++ b/src/components/ui/dialog/index.ts
@@ -0,0 +1,9 @@
+export { default as Dialog } from './Dialog.vue'
+export { default as DialogClose } from './DialogClose.vue'
+export { default as DialogTrigger } from './DialogTrigger.vue'
+export { default as DialogHeader } from './DialogHeader.vue'
+export { default as DialogTitle } from './DialogTitle.vue'
+export { default as DialogDescription } from './DialogDescription.vue'
+export { default as DialogContent } from './DialogContent.vue'
+export { default as DialogScrollContent } from './DialogScrollContent.vue'
+export { default as DialogFooter } from './DialogFooter.vue'
diff --git a/src/components/ui/dropdown-menu/DropdownMenu.vue b/src/components/ui/dropdown-menu/DropdownMenu.vue
new file mode 100644
index 0000000..b83d90b
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenu.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue b/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue
new file mode 100644
index 0000000..524664c
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuCheckboxItem.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuContent.vue b/src/components/ui/dropdown-menu/DropdownMenuContent.vue
new file mode 100644
index 0000000..ae81a53
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuContent.vue
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuGroup.vue b/src/components/ui/dropdown-menu/DropdownMenuGroup.vue
new file mode 100644
index 0000000..3f20135
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuGroup.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuItem.vue b/src/components/ui/dropdown-menu/DropdownMenuItem.vue
new file mode 100644
index 0000000..9769e7c
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuItem.vue
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuLabel.vue b/src/components/ui/dropdown-menu/DropdownMenuLabel.vue
new file mode 100644
index 0000000..5fa684e
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuLabel.vue
@@ -0,0 +1,24 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue b/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue
new file mode 100644
index 0000000..4a72790
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuRadioGroup.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue b/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue
new file mode 100644
index 0000000..f9f58c1
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuRadioItem.vue
@@ -0,0 +1,38 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue b/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue
new file mode 100644
index 0000000..1d95587
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuSeparator.vue
@@ -0,0 +1,22 @@
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue b/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue
new file mode 100644
index 0000000..abaeda6
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuShortcut.vue
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuSub.vue b/src/components/ui/dropdown-menu/DropdownMenuSub.vue
new file mode 100644
index 0000000..e0f4bd7
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuSub.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue b/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue
new file mode 100644
index 0000000..8c342a1
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuSubContent.vue
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue b/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue
new file mode 100644
index 0000000..00d04e0
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuSubTrigger.vue
@@ -0,0 +1,33 @@
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue b/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue
new file mode 100644
index 0000000..8efd5a9
--- /dev/null
+++ b/src/components/ui/dropdown-menu/DropdownMenuTrigger.vue
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/dropdown-menu/index.ts b/src/components/ui/dropdown-menu/index.ts
new file mode 100644
index 0000000..6f9446c
--- /dev/null
+++ b/src/components/ui/dropdown-menu/index.ts
@@ -0,0 +1,16 @@
+export { DropdownMenuPortal } from 'radix-vue'
+
+export { default as DropdownMenu } from './DropdownMenu.vue'
+export { default as DropdownMenuTrigger } from './DropdownMenuTrigger.vue'
+export { default as DropdownMenuContent } from './DropdownMenuContent.vue'
+export { default as DropdownMenuGroup } from './DropdownMenuGroup.vue'
+export { default as DropdownMenuRadioGroup } from './DropdownMenuRadioGroup.vue'
+export { default as DropdownMenuItem } from './DropdownMenuItem.vue'
+export { default as DropdownMenuCheckboxItem } from './DropdownMenuCheckboxItem.vue'
+export { default as DropdownMenuRadioItem } from './DropdownMenuRadioItem.vue'
+export { default as DropdownMenuShortcut } from './DropdownMenuShortcut.vue'
+export { default as DropdownMenuSeparator } from './DropdownMenuSeparator.vue'
+export { default as DropdownMenuLabel } from './DropdownMenuLabel.vue'
+export { default as DropdownMenuSub } from './DropdownMenuSub.vue'
+export { default as DropdownMenuSubTrigger } from './DropdownMenuSubTrigger.vue'
+export { default as DropdownMenuSubContent } from './DropdownMenuSubContent.vue'
diff --git a/src/components/ui/hover-card/HoverCard.vue b/src/components/ui/hover-card/HoverCard.vue
new file mode 100644
index 0000000..27c984c
--- /dev/null
+++ b/src/components/ui/hover-card/HoverCard.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/hover-card/HoverCardContent.vue b/src/components/ui/hover-card/HoverCardContent.vue
new file mode 100644
index 0000000..0986328
--- /dev/null
+++ b/src/components/ui/hover-card/HoverCardContent.vue
@@ -0,0 +1,37 @@
+
+
+
+
+
+
+
+
+
diff --git a/src/components/ui/hover-card/HoverCardTrigger.vue b/src/components/ui/hover-card/HoverCardTrigger.vue
new file mode 100644
index 0000000..d51aeda
--- /dev/null
+++ b/src/components/ui/hover-card/HoverCardTrigger.vue
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/hover-card/index.ts b/src/components/ui/hover-card/index.ts
new file mode 100644
index 0000000..78e8a7e
--- /dev/null
+++ b/src/components/ui/hover-card/index.ts
@@ -0,0 +1,3 @@
+export {default as HoverCard} from "./HoverCard.vue";
+export {default as HoverCardTrigger} from "./HoverCardTrigger.vue";
+export {default as HoverCardContent} from "./HoverCardContent.vue";
diff --git a/src/components/ui/skeleton/Skeleton.vue b/src/components/ui/skeleton/Skeleton.vue
new file mode 100644
index 0000000..ad3836c
--- /dev/null
+++ b/src/components/ui/skeleton/Skeleton.vue
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/src/components/ui/skeleton/index.ts b/src/components/ui/skeleton/index.ts
new file mode 100644
index 0000000..6515b49
--- /dev/null
+++ b/src/components/ui/skeleton/index.ts
@@ -0,0 +1 @@
+export {default as Skeleton} from "./Skeleton.vue";
diff --git a/src/enum/RoutesEnum.ts b/src/enum/RoutesEnum.ts
new file mode 100644
index 0000000..4208d3c
--- /dev/null
+++ b/src/enum/RoutesEnum.ts
@@ -0,0 +1,113 @@
+// biome-ignore lint/complexity/noStaticOnlyClass:
+export class RoutesEnum {
+ private static settings = "configurações";
+ private static graphs = "gráficos";
+ private static reminderCreate = "criar";
+ private static home = "página inicial";
+ private static reminder = "seus lembretes";
+
+ private static angry = "raiva";
+ private static sad = "tristeza";
+ private static envy = "inveja";
+ private static disgust = "nojinho";
+ private static happiness = "alegria";
+ private static fear = "medo";
+ private static shame = "vergonha";
+ private static boredom = "tédio";
+ private static anxiety = "ansiedade";
+
+ private static TextExhibitionList = {
+ [ RoutesEnum.settings ]: "Configurações",
+ [ RoutesEnum.reminder ]: "Seus Lembretes",
+ [ RoutesEnum.graphs ]: "Gráficos",
+ [ RoutesEnum.home ]: "Página inicial",
+ [ RoutesEnum.reminderCreate ]: "Criar",
+ [ RoutesEnum.angry ]: "Raiva",
+ [ RoutesEnum.sad ]: "Tristeza",
+ [ RoutesEnum.envy ]: "Inveja",
+ [ RoutesEnum.disgust ]: "Nojinho",
+ [ RoutesEnum.happiness ]: "Alegria",
+ [ RoutesEnum.fear ]: "Medo",
+ [ RoutesEnum.shame ]: "Vergonha",
+ [ RoutesEnum.boredom ]: "Tédio",
+ [ RoutesEnum.anxiety ]: "Ansiedade",
+ };
+
+ public static findClosestTextMatch(input: string): string | undefined {
+ let closestMatch = undefined;
+ let closestMatchLength = Number.POSITIVE_INFINITY;
+ let highestSimilarityScore = -1;
+
+ if (input === "" || input === undefined || input === null) {
+ return "";
+ }
+
+ for (const text of Object.values(RoutesEnum.TextExhibitionList)) {
+ const lowerCaseText = text.toLowerCase();
+ const lowerCaseInput = input.toLowerCase();
+
+ let similarityScore = 0;
+ let searchPosition = 0;
+ for (const char of lowerCaseInput) {
+ const foundPosition = lowerCaseText.indexOf(char, searchPosition);
+ if (foundPosition !== -1) {
+ similarityScore++;
+ searchPosition = foundPosition + 1;
+ } else {
+ break;
+ }
+ }
+
+ const lengthDifference = Math.abs(input.length - text.length);
+ if (
+ similarityScore > highestSimilarityScore ||
+ (similarityScore === highestSimilarityScore &&
+ lengthDifference < closestMatchLength)
+ ) {
+ closestMatch = text;
+ closestMatchLength = lengthDifference;
+ highestSimilarityScore = similarityScore;
+ }
+ }
+
+ return closestMatch;
+ }
+
+ private static graphsMatch = "Gráficos";
+ private static homeMatch = "Página inicial";
+ private static reminderCreateMatch = "Criar";
+ private static reminderMatch = "Seus Lembretes";
+ private static settingsMatch = "Configurações";
+ private static angryMatch = "Raiva";
+ private static sadMatch = "Tristeza";
+ private static envyMatch = "Inveja";
+ private static disgustMatch = "Nojinho";
+ private static happinessMatch = "Alegria";
+ private static fearMatch = "Medo";
+ private static shameMatch = "Vergonha";
+ private static boredomMatch = "Tédio";
+ private static anxietyMatch = "Ansiedade";
+
+ private static RouteTypeList = {
+ [ RoutesEnum.graphsMatch ]: "/graphs",
+ [ RoutesEnum.homeMatch ]: "/",
+ [ RoutesEnum.reminderCreateMatch ]: "/reminders/create",
+ [ RoutesEnum.reminderMatch ]: "/reminders",
+ [ RoutesEnum.settingsMatch ]: "/settings",
+ [ RoutesEnum.angryMatch ]: "/reminders/angry?page=1",
+ [ RoutesEnum.sadMatch ]: "/reminders/sad?page=1",
+ [ RoutesEnum.envyMatch ]: "/reminders/envy?page=1",
+ [ RoutesEnum.disgustMatch ]: "/reminders/disgust?page=1",
+ [ RoutesEnum.happinessMatch ]: "/reminders/happiness?page=1",
+ [ RoutesEnum.fearMatch ]: "/reminders/fear?page=1",
+ [ RoutesEnum.shameMatch ]: "/reminders/shame?page=1",
+ [ RoutesEnum.boredomMatch ]: "/reminders/boredom?page=1",
+ [ RoutesEnum.anxietyMatch ]: "/reminders/anxiety?page=1",
+ };
+
+ public static findClosestRouteMatch(input: string): string {
+ const closestTextMatch = RoutesEnum.findClosestTextMatch(input);
+
+ return RoutesEnum.RouteTypeList[ closestTextMatch as string ];
+ }
+}
diff --git a/src/router/index.ts b/src/router/index.ts
index ffb5384..a11311e 100644
--- a/src/router/index.ts
+++ b/src/router/index.ts
@@ -1,21 +1,75 @@
import {createRouter, createWebHistory} from "vue-router";
import Home from "@/views/Home.vue";
-import About from "@/views/About.vue";
+import AboutUs from "@/views/AboutUs.vue";
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: "/",
- name: "home",
+ name: "Home",
component: Home,
+ meta: {
+ title: "Home | NEI Market Analytics",
+ description:
+ "Welcome to NEI Market Analytics, your source for comprehensive market analysis.",
+ keywords: "market analysis, business insights, NEI Market Analytics",
+ robots: "index, follow",
+ ogTitle: "Home | NEI Market Analytics",
+ ogDescription:
+ "Welcome to NEI Market Analytics, your source for comprehensive market analysis.",
+ ogImage: "/logo.svg",
+ ogUrl: "http://localhost:5173/",
+ },
},
{
- path: "/about",
- name: "about",
- component: About,
+ path: "/about-us",
+ name: "About Us",
+ component: AboutUs,
+ meta: {
+ title: "Sobre Nós | NEI Market Analytics",
+ description: "Learn more about NEI Market Analytics and our mission.",
+ keywords: "about us, NEI Market Analytics, company information",
+ robots: "index, follow",
+ ogTitle: "Sobre Nós | NEI Market Analytics",
+ ogDescription: "Learn more about NEI Market Analytics and our mission.",
+ ogImage: "/logo.svg",
+ ogUrl: "http://localhost:5173/aboutus",
+ },
},
],
});
+router.beforeEach((to, from, next) => {
+ document.title = (to.meta.title as string) || "NEI Market Analytics";
+
+ const metaTags = [
+ {name: "description", content: to.meta.description as string},
+ {name: "keywords", content: to.meta.keywords as string},
+ {name: "robots", content: to.meta.robots as string},
+ {property: "og:title", content: to.meta.ogTitle as string},
+ {property: "og:description", content: to.meta.ogDescription as string},
+ {property: "og:image", content: to.meta.ogImage as string},
+ {property: "og:url", content: to.meta.ogUrl as string},
+ ];
+
+ for (const tag of metaTags) {
+ const key = tag.name ? "name" : "property";
+ const value = tag.name || tag.property;
+ if (!value) continue;
+
+ let element = document.querySelector(`meta[${key}="${value}"]`);
+ if (element) {
+ element.setAttribute("content", tag.content);
+ } else {
+ element = document.createElement("meta");
+ element.setAttribute(key, value);
+ element.setAttribute("content", tag.content);
+ document.head.appendChild(element);
+ }
+ }
+
+ next();
+});
+
export default router;
diff --git a/src/tags/Image.vue b/src/tags/Image.vue
new file mode 100644
index 0000000..51a4f83
--- /dev/null
+++ b/src/tags/Image.vue
@@ -0,0 +1,19 @@
+
+
+
+
+
diff --git a/src/tags/Link.vue b/src/tags/Link.vue
new file mode 100644
index 0000000..e43d8c5
--- /dev/null
+++ b/src/tags/Link.vue
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
diff --git a/src/views/About.vue b/src/views/About.vue
deleted file mode 100644
index 6ed8d13..0000000
--- a/src/views/About.vue
+++ /dev/null
@@ -1,14 +0,0 @@
-
-
-
-
-
-
-
-
-
diff --git a/src/views/AboutUs.vue b/src/views/AboutUs.vue
new file mode 100644
index 0000000..889b569
--- /dev/null
+++ b/src/views/AboutUs.vue
@@ -0,0 +1,21 @@
+
+
+
+
+
+
Impulsionando o Futuro Juntos
+ Colaborando para um amanhã mais tecnológico.
+
+
+
+
Por Trás dos Códigos
+
+
+
+
+
diff --git a/src/views/Home.vue b/src/views/Home.vue
index 9956263..4424ece 100644
--- a/src/views/Home.vue
+++ b/src/views/Home.vue
@@ -1,14 +1,11 @@
-
-
-
+
+
+ NEI Market Analytics
diff --git a/stories/components/Accordion.stories.ts b/stories/components/Accordion.stories.ts
new file mode 100644
index 0000000..0132767
--- /dev/null
+++ b/stories/components/Accordion.stories.ts
@@ -0,0 +1,46 @@
+import type { Meta, StoryObj } from "@storybook/vue3";
+import { within, expect } from "@storybook/test";
+import Accordion from "@/components/Accordion.vue";
+import { AccordionDto } from "@/components/Dto/AccordionDto";
+
+const meta: Meta = {
+ title: "Components/Accordion",
+ component: Accordion,
+ tags: [ "autodocs" ],
+ parameters: {
+ actions: {
+ argTypesRegex: "^on.*",
+ },
+ },
+ argTypes: {
+ items: {
+ description: "The items of the Accordion",
+ example: AccordionDto,
+ control: { type: "object" },
+ },
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ name: "Default",
+ args: {
+ items: AccordionDto,
+ },
+ play: async ({ canvasElement, step }) => {
+ const canvas = within(canvasElement);
+
+ const AccordionElement = canvas.getByTestId("Accordion");
+ await step("Render the Accordion", async () => {
+ expect(AccordionElement).toBeDefined();
+ });
+
+ const AccordionClass = AccordionElement.getAttribute("class");
+ await step("Verify the Accordion class", async () => {
+ expect(AccordionClass).toBe("w-full");
+ });
+ },
+};
diff --git a/stories/components/Badges.stories.ts b/stories/components/Badges.stories.ts
new file mode 100644
index 0000000..7684815
--- /dev/null
+++ b/stories/components/Badges.stories.ts
@@ -0,0 +1,46 @@
+import type { Meta, StoryObj } from "@storybook/vue3";
+import { within, expect } from "@storybook/test";
+import Badges from "@/components/Badges.vue";
+import { BadgesDto } from "@/components/Dto/BadgesDto";
+
+const meta: Meta = {
+ title: "Components/Badges",
+ component: Badges,
+ tags: [ "autodocs" ],
+ parameters: {
+ actions: {
+ argTypesRegex: "^on.*",
+ },
+ },
+ argTypes: {
+ badges: {
+ description: "The badges of the Badges",
+ example: BadgesDto,
+ control: { type: "object" },
+ },
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ name: "Default",
+ args: {
+ badges: BadgesDto,
+ },
+ play: async ({ canvasElement, step }) => {
+ const canvas = within(canvasElement);
+
+ const BadgesElement = canvas.getByTestId("Badges");
+ await step("Render the Badges", async () => {
+ expect(BadgesElement).toBeDefined();
+ });
+
+ const BadgesClass = BadgesElement.getAttribute("class");
+ await step("Verify the Badges class", async () => {
+ expect(BadgesClass).toBe("flex gap-4 flex-wrap justify-center");
+ });
+ },
+};
diff --git a/stories/components/HoverCard.stories.ts b/stories/components/HoverCard.stories.ts
new file mode 100644
index 0000000..fc7dc0c
--- /dev/null
+++ b/stories/components/HoverCard.stories.ts
@@ -0,0 +1,66 @@
+import type { Meta, StoryObj } from "@storybook/vue3";
+import { within, expect } from "@storybook/test";
+import HoverCard from "@/components/HoverCard.vue";
+import { HoverCardMock } from "../../mocks/components/HoverCard";
+
+const meta: Meta = {
+ title: "Components/HoverCard",
+ component: HoverCard,
+ tags: [ "autodocs" ],
+ parameters: {
+ actions: {
+ argTypesRegex: "^on.*",
+ },
+ },
+ argTypes: {
+ title: {
+ description: "The title of the card",
+ example: "John Doe",
+ control: { type: "text" },
+ },
+ description: {
+ description: "The description of the card",
+ example: "Creator of Radix UI",
+ control: { type: "text" },
+ },
+ startDate: {
+ description: "The start date of the card",
+ example: "February 2022",
+ control: { type: "text" },
+ },
+ avatarSrc: {
+ description: "The avatar source of the card",
+ example: "https://avatars.githubusercontent.com/u/11473738?v=4",
+ control: { type: "text" },
+ },
+ avatarFallback: {
+ description: "The avatar fallback of the card",
+ example: "JD",
+ control: { type: "text" },
+ },
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ name: "Default",
+ args: HoverCardMock,
+ play: async ({ canvasElement, step }) => {
+ const canvas = within(canvasElement);
+
+ const HoverCardButtonElement = canvas.getByTestId("HoverCardButton");
+ await step("Render the HoverCardButton", async () => {
+ expect(HoverCardButtonElement).toBeDefined();
+ });
+
+ const HoverCardButtonClass = HoverCardButtonElement.getAttribute("class");
+ await step("Verify the HoverCardButton class", async () => {
+ expect(HoverCardButtonClass).toBe(
+ "inline-flex items-center whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 text-primary underline-offset-4 hover:underline h-9 p-0 justify-start w-fit",
+ );
+ });
+ },
+};
diff --git a/stories/components/Layout/Footer.stories.ts b/stories/components/Layout/Footer.stories.ts
new file mode 100644
index 0000000..0deb4b9
--- /dev/null
+++ b/stories/components/Layout/Footer.stories.ts
@@ -0,0 +1,35 @@
+import type { Meta, StoryObj } from "@storybook/vue3";
+import { within, expect } from "@storybook/test";
+import Footer from "@/components/Layout/Footer.vue";
+
+const meta: Meta = {
+ title: "Components/Layout/Footer",
+ component: Footer,
+ tags: [ "autodocs" ],
+ parameters: {
+ actions: {
+ argTypesRegex: "^on.*",
+ },
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ name: "Default",
+ play: async ({ canvasElement, step }) => {
+ const canvas = within(canvasElement);
+
+ const FooterElement = canvas.getByTestId("Footer");
+ await step("Render the Footer", async () => {
+ expect(FooterElement).toBeDefined();
+ });
+
+ const FooterClass = FooterElement.getAttribute("class");
+ await step("Verify the Footer class", async () => {
+ expect(FooterClass).toBe("layout container justify-center min-w-full border-t");
+ });
+ },
+};
diff --git a/stories/components/Layout/Header.stories.ts b/stories/components/Layout/Header.stories.ts
new file mode 100644
index 0000000..2a55ad8
--- /dev/null
+++ b/stories/components/Layout/Header.stories.ts
@@ -0,0 +1,35 @@
+import type { Meta, StoryObj } from "@storybook/vue3";
+import { within, expect } from "@storybook/test";
+import Header from "@/components/Layout/Header.vue";
+
+const meta: Meta = {
+ title: "Components/Layout/Header",
+ component: Header,
+ tags: [ "autodocs" ],
+ parameters: {
+ actions: {
+ argTypesRegex: "^on.*",
+ },
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ name: "Default",
+ play: async ({ canvasElement, step }) => {
+ const canvas = within(canvasElement);
+
+ const HeaderElement = canvas.getByTestId("Header");
+ await step("Render the Header", async () => {
+ expect(HeaderElement).toBeDefined();
+ });
+
+ const HeaderClass = HeaderElement.getAttribute("class");
+ await step("Verify the Header class", async () => {
+ expect(HeaderClass).toBe("layout container justify-center min-w-full border-b");
+ });
+ },
+};
diff --git a/stories/tags/Image.stories.ts b/stories/tags/Image.stories.ts
new file mode 100644
index 0000000..133da99
--- /dev/null
+++ b/stories/tags/Image.stories.ts
@@ -0,0 +1,80 @@
+import type {Meta, StoryObj} from "@storybook/vue3";
+import {within, expect} from "@storybook/test";
+import Image from "@/tags/Image.vue";
+import {ImageMock} from "../../mocks/components/tags/Image";
+
+const meta: Meta = {
+ title: "Components/Tags/Image",
+ component: Image,
+ tags: ["autodocs"],
+ parameters: {
+ actions: {
+ argTypesRegex: "^on.*",
+ },
+ },
+ argTypes: {
+ alt: {
+ description: "The alt of the image",
+ example: "image",
+ control: {type: "text"},
+ },
+ height: {
+ description: "The height of the image",
+ example: "80",
+ control: {type: "text"},
+ },
+ width: {
+ description: "The width of the image",
+ example: "80",
+ control: {type: "text"},
+ },
+ src: {
+ description: "The source of the image",
+ example: "https://via.placeholder.com/80",
+ control: {type: "text"},
+ },
+ class: {
+ description: "The class of the image",
+ example: "w-20 h-20",
+ control: {type: "text"},
+ },
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ name: "Default",
+ args: ImageMock,
+ play: async ({canvasElement, step}) => {
+ const canvas = within(canvasElement);
+
+ const ImageElement = canvas.getByTestId("Image");
+ await step("Render the Image", async () => {
+ expect(ImageElement).toBeDefined();
+ });
+
+ const ImageStyle = getComputedStyle(ImageElement);
+ await step("Verify the initial Image style", async () => {
+ expect(ImageStyle.height).toBe(`${ImageMock.height}px`);
+ expect(ImageStyle.width).toBe(`${ImageMock.width}px`);
+ });
+
+ const ImageAlt = ImageElement.getAttribute("alt");
+ await step("Verify the Image alt", async () => {
+ expect(ImageAlt).toBe(ImageMock.alt);
+ });
+
+ const ImageSrc = ImageElement.getAttribute("src");
+ await step("Verify the Image src", async () => {
+ expect(ImageSrc).toBe(ImageMock.src);
+ });
+
+ const ImageClass = ImageElement.getAttribute("class");
+ await step("Verify the Image class", async () => {
+ expect(ImageClass).toBe(ImageMock.class);
+ });
+ },
+};
diff --git a/stories/tags/Link.stories.ts b/stories/tags/Link.stories.ts
new file mode 100644
index 0000000..202549c
--- /dev/null
+++ b/stories/tags/Link.stories.ts
@@ -0,0 +1,70 @@
+import type { Meta, StoryObj } from "@storybook/vue3";
+import { within, expect } from "@storybook/test";
+import Link from "@/tags/Link.vue";
+import { LinkMock } from "../../mocks/components/tags/Link";
+
+const meta: Meta = {
+ title: "Components/Tags/Link",
+ component: Link,
+ tags: [ "autodocs" ],
+ parameters: {
+ actions: {
+ argTypesRegex: "^on.*",
+ },
+ },
+ argTypes: {
+ href: {
+ description: "The href of the link",
+ example: "https://www.google.com",
+ control: { type: "text" },
+ },
+ target: {
+ description: "The target of the link",
+ example: "_blank",
+ control: { type: "select" },
+ options: [ "_blank", "_self", "_parent", "_top" ],
+ },
+ class: {
+ description: "The class of the link",
+ example: "text-blue",
+ control: { type: "text" },
+ },
+ },
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+export const Default: Story = {
+ name: "Default",
+ args: { ...LinkMock, default: "Click here" },
+ play: async ({ canvasElement, step }) => {
+ const canvas = within(canvasElement);
+
+ const LinkElement = canvas.getByTestId("Link");
+ await step("Render the Link", async () => {
+ expect(LinkElement).toBeDefined();
+ });
+
+ const LinkClass = LinkElement.getAttribute("class");
+ await step("Verify the Link class", async () => {
+ expect(LinkClass).toBe(LinkMock.class);
+ });
+
+ const LinkHref = LinkElement.getAttribute("href");
+ await step("Verify the Link href", async () => {
+ expect(LinkHref).toBe(LinkMock.href);
+ });
+
+ const LinkTarget = LinkElement.getAttribute("target");
+ await step("Verify the Link target", async () => {
+ expect(LinkTarget).toBe(LinkMock.target);
+ });
+
+ const LinkRel = LinkElement.getAttribute("rel");
+ await step("Verify the Link rel", async () => {
+ expect(LinkRel).toBe("no-referrer");
+ });
+ },
+};
diff --git a/tailwind.config.js b/tailwind.config.js
index fa1ff29..cd42cdd 100644
--- a/tailwind.config.js
+++ b/tailwind.config.js
@@ -1,121 +1,121 @@
import animate from "tailwindcss-animate";
/** @type {import('tailwindcss').Config} */
-export const darkMode = [ "class" ];
-export const safelist = [ "dark" ];
+export const darkMode = ["class"];
+export const safelist = ["dark"];
export const prefix = "";
-export const content = [ "./src/**/*.{ts,tsx,vue}" ];
+export const content = ["./src/**/*.{ts,tsx,vue}"];
export const theme = {
- container: {
- center: true,
- padding: "2rem",
- screens: {
- "2xl": "1400px",
- },
- },
- extend: {
- colors: {
- primaryForeground: "var(--primary-foreground)",
- secondaryForeground: "var(--secondary-foreground)",
- material: "var(--material)",
- texture: "var(--texture)",
- positive: "var(--positive)",
- negative: "var(--negative)",
- positiveLighter: "var(--positive-lighter)",
- positiveDarker: "var(--positive-darker)",
- negativeLighter: "var(--negative-lighter)",
- negativeDarker: "var(--negative-darker)",
- fg: "var(--fg)",
- fgDim: "var(--fg-dim)",
- fgMuted: "var(--fg-muted)",
- secondaryLighter: "var(--secondary-lighter)",
- secondaryDarker: "var(--secondary-darker)",
- surfaceLighter: "var(--surface-lighter)",
- surfaceDarker: "var(--surface-darker)",
- materialLighter: "var(--material-lighter)",
- materialDarker: "var(--material-darker)",
- textureLighter: "var(--texture-lighter)",
- textureDarker: "var(--texture-darker)",
- onPrimary: "var(--on-primary)",
- twitter: "var(--twitter)",
- telegram: "var(--telegram)",
- reddit: "var(--reddit)",
- facebook: "var(--facebook)",
- medium: "var(--medium)",
- github: "var(--github)",
- discord: "var(--discord)",
- linkedin: "var(--linkedin)",
- instagram: "var(--instagram)",
- youtube: "var(--youtube)",
- 'primary-lighter': "var(--primary-lighter)",
- 'primary-darker': "var(--primary-darker)",
- background: "var(--background)",
- surface: "var(--surface)",
- blue: "var(--blue)",
- text: "var(--text)",
- border: "var(--border)",
- input: "var(--input)",
- ring: "var(--ring)",
- foreground: "var(--foreground)",
- primary: {
- DEFAULT: "var(--primary)",
- foreground: "var(--primary-foreground)",
- },
- secondary: {
- DEFAULT: "var(--secondary)",
- foreground: "var(--secondary-foreground)",
- },
- destructive: {
- DEFAULT: "var(--destructive)",
- foreground: "var(--destructive-foreground)",
- },
- muted: {
- DEFAULT: "var(--muted)",
- foreground: "var(--muted-foreground)",
- },
- accent: {
- DEFAULT: "var(--accent)",
- foreground: "var(--accent-foreground)",
- },
- popover: {
- DEFAULT: "var(--popover)",
- foreground: "var(--popover-foreground)",
- },
- card: {
- DEFAULT: "var(--card)",
- foreground: "var(--card-foreground)",
- },
- },
- borderRadius: {
- xl: "calc(var(--radius) + 4px)",
- lg: "var(--radius)",
- md: "calc(var(--radius) - 2px)",
- sm: "calc(var(--radius) - 4px)",
- },
- keyframes: {
- "accordion-down": {
- from: { height: 0 },
- to: { height: "var(--radix-accordion-content-height)" },
- },
- "accordion-up": {
- from: { height: "var(--radix-accordion-content-height)" },
- to: { height: 0 },
- },
- "collapsible-down": {
- from: { height: 0 },
- to: { height: "var(--radix-collapsible-content-height)" },
- },
- "collapsible-up": {
- from: { height: "var(--radix-collapsible-content-height)" },
- to: { height: 0 },
- },
- },
- animation: {
- "accordion-down": "accordion-down 0.2s ease-out",
- "accordion-up": "accordion-up 0.2s ease-out",
- "collapsible-down": "collapsible-down 0.2s ease-in-out",
- "collapsible-up": "collapsible-up 0.2s ease-in-out",
- },
- },
+ container: {
+ center: true,
+ padding: "2rem",
+ screens: {
+ "2xl": "1400px",
+ },
+ },
+ extend: {
+ colors: {
+ primaryForeground: "var(--primary-foreground)",
+ textForeground: "var(--text-foreground)",
+ material: "var(--material)",
+ dark: "var(--dark)",
+ texture: "var(--texture)",
+ positive: "var(--positive)",
+ negative: "var(--negative)",
+ positiveLighter: "var(--positive-lighter)",
+ positiveDarker: "var(--positive-darker)",
+ negativeLighter: "var(--negative-lighter)",
+ negativeDarker: "var(--negative-darker)",
+ fg: "var(--fg)",
+ fgDim: "var(--fg-dim)",
+ fgMuted: "var(--fg-muted)",
+ secondaryDarker: "var(--secondary-darker)",
+ surfaceLighter: "var(--surface-lighter)",
+ surfaceDarker: "var(--surface-darker)",
+ materialLighter: "var(--material-lighter)",
+ materialDarker: "var(--material-darker)",
+ textureLighter: "var(--texture-lighter)",
+ textureDarker: "var(--texture-darker)",
+ onPrimary: "var(--on-primary)",
+ twitter: "var(--twitter)",
+ telegram: "var(--telegram)",
+ reddit: "var(--reddit)",
+ facebook: "var(--facebook)",
+ medium: "var(--medium)",
+ github: "var(--github)",
+ discord: "var(--discord)",
+ linkedin: "var(--linkedin)",
+ instagram: "var(--instagram)",
+ youtube: "var(--youtube)",
+ "primary-lighter": "var(--primary-lighter)",
+ "primary-darker": "var(--primary-darker)",
+ background: "var(--background)",
+ surface: "var(--surface)",
+ blue: "var(--blue)",
+ text: "var(--text)",
+ border: "var(--border)",
+ input: "var(--input)",
+ ring: "var(--ring)",
+ foreground: "var(--foreground)",
+ primary: {
+ DEFAULT: "var(--primary)",
+ foreground: "var(--primary-foreground)",
+ },
+ secondary: {
+ DEFAULT: "var(--secondary)",
+ foreground: "var(--secondary-foreground)",
+ },
+ destructive: {
+ DEFAULT: "var(--destructive)",
+ foreground: "var(--destructive-foreground)",
+ },
+ muted: {
+ DEFAULT: "var(--muted)",
+ foreground: "var(--muted-foreground)",
+ },
+ accent: {
+ DEFAULT: "var(--accent)",
+ foreground: "var(--accent-foreground)",
+ },
+ popover: {
+ DEFAULT: "var(--popover)",
+ foreground: "var(--popover-foreground)",
+ },
+ card: {
+ DEFAULT: "var(--card)",
+ foreground: "var(--card-foreground)",
+ },
+ },
+ borderRadius: {
+ xl: "calc(var(--radius) + 4px)",
+ lg: "var(--radius)",
+ md: "calc(var(--radius) - 2px)",
+ sm: "calc(var(--radius) - 4px)",
+ },
+ keyframes: {
+ "accordion-down": {
+ from: {height: 0},
+ to: {height: "var(--radix-accordion-content-height)"},
+ },
+ "accordion-up": {
+ from: {height: "var(--radix-accordion-content-height)"},
+ to: {height: 0},
+ },
+ "collapsible-down": {
+ from: {height: 0},
+ to: {height: "var(--radix-collapsible-content-height)"},
+ },
+ "collapsible-up": {
+ from: {height: "var(--radix-collapsible-content-height)"},
+ to: {height: 0},
+ },
+ },
+ animation: {
+ "accordion-down": "accordion-down 0.2s ease-out",
+ "accordion-up": "accordion-up 0.2s ease-out",
+ "collapsible-down": "collapsible-down 0.2s ease-in-out",
+ "collapsible-up": "collapsible-up 0.2s ease-in-out",
+ },
+ },
};
-export const plugins = [ animate ];
\ No newline at end of file
+export const plugins = [animate];
diff --git a/tests/components/Accordion.spec.ts b/tests/components/Accordion.spec.ts
new file mode 100644
index 0000000..b612aa9
--- /dev/null
+++ b/tests/components/Accordion.spec.ts
@@ -0,0 +1,35 @@
+import {test, expect, describe} from "vitest";
+import Accordion from "@/components/Accordion.vue";
+import {mount} from "@vue/test-utils";
+import {AccordionDto} from "@/components/Dto/AccordionDto";
+
+describe("Accordion Component Tests", () => {
+ const wrapper = mount(Accordion);
+ const accordionComponent = wrapper.findComponent(Accordion);
+
+ test("Should be able to render the component correctly", async () => {
+ expect(accordionComponent).toBeDefined();
+ });
+
+ test("Should be able to snapshot the component correctly", async () => {
+ expect(accordionComponent.html()).toMatchSnapshot();
+ });
+
+ test("Should be able to render the component with the correct text", async () => {
+ for (const item of AccordionDto) {
+ expect(accordionComponent.text()).toContain(item.title);
+ }
+ });
+
+ test("Should be able to render the component with the correct classes", async () => {
+ expect(accordionComponent.classes()).toStrictEqual(["w-full"]);
+ });
+
+ test("Should have the correct collapsible prop", async () => {
+ expect(accordionComponent.props("collapsible")).toBe(true);
+ });
+
+ test("Should have the correct type prop", async () => {
+ expect(accordionComponent.props("type")).toBe("single");
+ });
+});
diff --git a/tests/components/Badges.spec.ts b/tests/components/Badges.spec.ts
new file mode 100644
index 0000000..82162cb
--- /dev/null
+++ b/tests/components/Badges.spec.ts
@@ -0,0 +1,34 @@
+import {test, expect, describe} from "vitest";
+import Badges from "@/components/Badges.vue";
+import {mount} from "@vue/test-utils";
+import {BadgesDto} from "@/components/Dto/BadgesDto";
+
+describe("Badges Component Tests", () => {
+ const wrapper = mount(Badges);
+ const badgesComponent = wrapper.findComponent(Badges);
+
+ test("Should be able to render the component correctly", async () => {
+ expect(badgesComponent).toBeDefined();
+ });
+
+ test("Should be able to snapshot the component correctly", async () => {
+ expect(badgesComponent.html()).toMatchSnapshot();
+ });
+
+ test("Should be able to render the component with the correct text", async () => {
+ for (const item of BadgesDto) {
+ expect(badgesComponent.text()).toContain(item.name);
+ expect(badgesComponent.text()).toContain(item.nickname);
+ expect(badgesComponent.text()).toContain(item.occupation);
+ }
+ });
+
+ test("Should be able to render the component with the correct classes", async () => {
+ expect(badgesComponent.classes()).toStrictEqual([
+ "flex",
+ "gap-4",
+ "flex-wrap",
+ "justify-center",
+ ]);
+ });
+});
diff --git a/tests/components/HoverCard.spec.ts b/tests/components/HoverCard.spec.ts
new file mode 100644
index 0000000..2193861
--- /dev/null
+++ b/tests/components/HoverCard.spec.ts
@@ -0,0 +1,28 @@
+import { test, expect, describe } from "vitest";
+import HoverCard from "@/components/HoverCard.vue";
+import { mount } from "@vue/test-utils";
+import { HoverCardMock } from "../../mocks/components/HoverCard";
+import type { HoverCardProps } from "@/components/HoverCard.vue";
+
+describe("HoverCard Component Tests", () => {
+ const wrapper = mount(HoverCard, { props: { ...HoverCardMock } });
+ const hoverCardComponent = wrapper.findComponent(HoverCard);
+
+ test("Should be able to render the component correctly", async () => {
+ expect(hoverCardComponent).toBeDefined();
+ });
+
+ test("Should be able to snapshot the component correctly", async () => {
+ expect(hoverCardComponent.html()).toMatchSnapshot();
+ });
+
+ test("Should be able to render the component with the correct props", async () => {
+ for (const attr in hoverCardComponent.vm.$attrs) {
+ expect(hoverCardComponent.vm.$attrs[ attr as keyof HoverCardProps ]).toBe(HoverCardMock[ attr as keyof HoverCardProps ]);
+ }
+ });
+
+ test("Should be able to hover the component", async () => {
+ expect(hoverCardComponent.trigger("mouseenter")).toBeDefined();
+ });
+});
diff --git a/tests/components/Layout/Footer.spec.ts b/tests/components/Layout/Footer.spec.ts
new file mode 100644
index 0000000..44926cb
--- /dev/null
+++ b/tests/components/Layout/Footer.spec.ts
@@ -0,0 +1,30 @@
+import {test, expect, describe} from "vitest";
+import Footer from "@/components/Layout/Footer.vue";
+import {mount} from "@vue/test-utils";
+
+describe("Footer Component Tests", () => {
+ const wrapper = mount(Footer);
+ const footerComponent = wrapper.findComponent(Footer);
+
+ test("Should be able to render the component correctly", async () => {
+ expect(footerComponent).toBeDefined();
+ });
+
+ test("Should be able to snapshot the component correctly", async () => {
+ expect(footerComponent.html()).toMatchSnapshot();
+ });
+
+ test("Should be able to render the component with the correct text", async () => {
+ expect(footerComponent.text()).toStrictEqual("Footer");
+ });
+
+ test("Should be able to render the component with the correct classes", async () => {
+ expect(footerComponent.classes()).toStrictEqual([
+ "layout",
+ "container",
+ "justify-center",
+ "min-w-full",
+ "border-t",
+ ]);
+ });
+});
diff --git a/tests/components/Layout/Header.spec.ts b/tests/components/Layout/Header.spec.ts
new file mode 100644
index 0000000..d49cdde
--- /dev/null
+++ b/tests/components/Layout/Header.spec.ts
@@ -0,0 +1,30 @@
+import {test, expect, describe} from "vitest";
+import Header from "@/components/Layout/Header.vue";
+import {mount} from "@vue/test-utils";
+
+describe("Header Component Tests", () => {
+ const wrapper = mount(Header);
+ const headerComponent = wrapper.findComponent(Header);
+
+ test("Should be able to render the component correctly", async () => {
+ expect(headerComponent).toBeDefined();
+ });
+
+ test("Should be able to snapshot the component correctly", async () => {
+ expect(headerComponent.html()).toMatchSnapshot();
+ });
+
+ test("Should be able to render the component with the correct text", async () => {
+ expect(headerComponent.text()).toStrictEqual("Header");
+ });
+
+ test("Should be able to render the component with the correct classes", async () => {
+ expect(headerComponent.classes()).toStrictEqual([
+ "layout",
+ "container",
+ "justify-center",
+ "min-w-full",
+ "border-b",
+ ]);
+ });
+});
diff --git a/tests/components/Layout/__snapshots__/Footer.spec.ts.snap b/tests/components/Layout/__snapshots__/Footer.spec.ts.snap
new file mode 100644
index 0000000..1a94e8f
--- /dev/null
+++ b/tests/components/Layout/__snapshots__/Footer.spec.ts.snap
@@ -0,0 +1,3 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Footer Component Tests > Should be able to snapshot the component correctly 1`] = `""`;
diff --git a/tests/components/Layout/__snapshots__/Header.spec.ts.snap b/tests/components/Layout/__snapshots__/Header.spec.ts.snap
new file mode 100644
index 0000000..4d73d92
--- /dev/null
+++ b/tests/components/Layout/__snapshots__/Header.spec.ts.snap
@@ -0,0 +1,3 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Header Component Tests > Should be able to snapshot the component correctly 1`] = `""`;
diff --git a/tests/components/__snapshots__/Accordion.spec.ts.snap b/tests/components/__snapshots__/Accordion.spec.ts.snap
new file mode 100644
index 0000000..996e9f0
--- /dev/null
+++ b/tests/components/__snapshots__/Accordion.spec.ts.snap
@@ -0,0 +1,30 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Accordion Component Tests > Should be able to snapshot the component correctly 1`] = `
+"
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
"
+`;
diff --git a/tests/components/__snapshots__/Badges.spec.ts.snap b/tests/components/__snapshots__/Badges.spec.ts.snap
new file mode 100644
index 0000000..297a822
--- /dev/null
+++ b/tests/components/__snapshots__/Badges.spec.ts.snap
@@ -0,0 +1,54 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Badges Component Tests > Should be able to snapshot the component correctly 1`] = `
+"
+ -
+
+
+
+
+
+
Victor Navarro
Software Engineer
+
+
+
+
+
+ -
+
+
+
+
+
+
Erackson Souza
Frontend Developer
+
+
+
+
+
+ -
+
+
+
+
+
+
Israel Pina
FullStack Developer
+
+
+
+
+
+
"
+`;
diff --git a/tests/components/__snapshots__/HoverCard.spec.ts.snap b/tests/components/__snapshots__/HoverCard.spec.ts.snap
new file mode 100644
index 0000000..3a890b2
--- /dev/null
+++ b/tests/components/__snapshots__/HoverCard.spec.ts.snap
@@ -0,0 +1,7 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`HoverCard Component Tests > Should be able to snapshot the component correctly 1`] = `
+"
+
+"
+`;
diff --git a/tests/tags/Image.spec.ts b/tests/tags/Image.spec.ts
new file mode 100644
index 0000000..f571bfc
--- /dev/null
+++ b/tests/tags/Image.spec.ts
@@ -0,0 +1,25 @@
+import { test, expect, describe } from "vitest";
+import Image from "@/tags/Image.vue";
+import { ImageMock } from "../../mocks/components/tags/Image";
+import { mount } from "@vue/test-utils";
+
+describe("Image Component Tests", () => {
+ const wrapper = mount(Image, { props: { ...ImageMock } });
+ const imageComponent = wrapper.findComponent(Image);
+
+ test("Should be able to render the component correctly", async () => {
+ expect(imageComponent).toBeDefined();
+ });
+
+ test("Should be able to snapshot the component correctly", async () => {
+ expect(imageComponent.html()).toMatchSnapshot();
+ });
+
+ test("Should be able to render the component with the correct props", async () => {
+ expect(imageComponent.props("src")).toBe(ImageMock.src);
+ expect(imageComponent.props("alt")).toBe(ImageMock.alt);
+ expect(imageComponent.props("width")).toBe(ImageMock.width);
+ expect(imageComponent.props("height")).toBe(ImageMock.height);
+ expect(imageComponent.props("class")).toBe(ImageMock.class);
+ });
+});
diff --git a/tests/tags/Link.spec.ts b/tests/tags/Link.spec.ts
new file mode 100644
index 0000000..e663cfb
--- /dev/null
+++ b/tests/tags/Link.spec.ts
@@ -0,0 +1,39 @@
+import { test, expect, describe } from "vitest";
+import Link from "@/tags/Link.vue";
+import { LinkMock } from "../../mocks/components/tags/Link";
+import { mount } from "@vue/test-utils";
+
+describe("Link Component Tests", () => {
+ const wrapper = mount(Link, {
+ props: { ...LinkMock }, slots: {
+ default: 'Texto do Link'
+ }
+ });
+ const linkComponent = wrapper.findComponent(Link);
+
+ test("Should be able to render the component correctly", async () => {
+ expect(linkComponent).toBeDefined();
+ });
+
+ test("Should be able to snapshot the component correctly", async () => {
+ expect(linkComponent.html()).toMatchSnapshot();
+ });
+
+ test("Should be able to render the component with the correct props", async () => {
+ expect(linkComponent.props("href")).toBe(LinkMock.href);
+ expect(linkComponent.props("target")).toBe(LinkMock.target);
+ expect(linkComponent.props("class")).toBe(LinkMock.class);
+ });
+
+ test("Should be able to render the component with the correct rel", async () => {
+ expect(linkComponent.attributes("rel")).toBe("no-referrer");
+ });
+
+ test("Should be able to render the component with the correct text", async () => {
+ expect(linkComponent.text()).toBe("Texto do Link");
+ });
+
+ test("Should be able to hover the component", async () => {
+ expect(linkComponent.trigger("mouseenter")).toBeDefined();
+ });
+});
diff --git a/tests/tags/__snapshots__/Image.spec.ts.snap b/tests/tags/__snapshots__/Image.spec.ts.snap
new file mode 100644
index 0000000..7cb9448
--- /dev/null
+++ b/tests/tags/__snapshots__/Image.spec.ts.snap
@@ -0,0 +1,3 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Image Component Tests > Should be able to snapshot the component correctly 1`] = `""`;
diff --git a/tests/tags/__snapshots__/Link.spec.ts.snap b/tests/tags/__snapshots__/Link.spec.ts.snap
new file mode 100644
index 0000000..e45e398
--- /dev/null
+++ b/tests/tags/__snapshots__/Link.spec.ts.snap
@@ -0,0 +1,3 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`Link Component Tests > Should be able to snapshot the component correctly 1`] = `"Texto do Link"`;
diff --git a/tsconfig.app.json b/tsconfig.app.json
index 7a49c72..e62434d 100644
--- a/tsconfig.app.json
+++ b/tsconfig.app.json
@@ -1,6 +1,6 @@
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
- "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
+ "include": ["env.d.ts", "src/**/*", "src/**/*.vue", "tests/**/*", "stories/**/*", "mocks/**/*"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,
diff --git a/vite.config.ts b/vite.config.ts
index 58a629c..b1ca6fc 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,6 +1,6 @@
-import {fileURLToPath, URL} from "node:url";
+import { fileURLToPath, URL } from "node:url";
-import {defineConfig} from "vite";
+import { defineConfig } from "vite";
import vue from "@vitejs/plugin-vue";
import vueJsx from "@vitejs/plugin-vue-jsx";
import vueDevTools from "vite-plugin-vue-devtools";
@@ -8,35 +8,35 @@ import tailwind from "tailwindcss";
import autoprefixer from "autoprefixer";
export default defineConfig({
- plugins: [vue(), vueJsx(), vueDevTools()],
- resolve: {
- alias: {
- "@": fileURLToPath(new URL("./src", import.meta.url)),
- },
- },
- css: {
- postcss: {
- plugins: [tailwind(), autoprefixer()],
- },
- },
- optimizeDeps: {
- include: [
- "vue",
- "vue-router",
- "@vueuse/core",
- "pinia",
- "@storybook/blocks",
- "@storybook/theming",
- "@storybook/addon-links/preview",
- "@storybook/addon-essentials/docs/preview",
- "@storybook/addon-essentials/actions/preview",
- "@storybook/addon-essentials/backgrounds/preview",
- "@storybook/addon-essentials/viewport/preview",
- "@storybook/addon-essentials/measure/preview",
- "@storybook/addon-essentials/outline/preview",
- "@storybook/addon-essentials/highlight/preview",
- "@storybook/addon-interactions/preview",
- "@storybook/addon-actions/decorator",
- ],
- },
+ plugins: [ vue(), vueJsx(), vueDevTools() ],
+ resolve: {
+ alias: {
+ "@": fileURLToPath(new URL("./src", import.meta.url)),
+ },
+ },
+ css: {
+ postcss: {
+ plugins: [ tailwind(), autoprefixer() ],
+ },
+ },
+ optimizeDeps: {
+ include: [
+ "vue",
+ "vue-router",
+ "@vueuse/core",
+ "pinia",
+ "@storybook/blocks",
+ "@storybook/theming",
+ "@storybook/addon-links/preview",
+ "@storybook/addon-essentials/docs/preview",
+ "@storybook/addon-essentials/actions/preview",
+ "@storybook/addon-essentials/backgrounds/preview",
+ "@storybook/addon-essentials/viewport/preview",
+ "@storybook/addon-essentials/measure/preview",
+ "@storybook/addon-essentials/outline/preview",
+ "@storybook/addon-essentials/highlight/preview",
+ "@storybook/addon-interactions/preview",
+ "@storybook/addon-actions/decorator",
+ ],
+ },
});