diff --git a/.env.examples b/.env.examples
index e69de29..ec2852e 100644
--- a/.env.examples
+++ b/.env.examples
@@ -0,0 +1 @@
+VITE_ENDPOINT_URL=
\ No newline at end of file
diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml
index 54d9723..ec8fc79 100644
--- a/.github/workflows/CI.yml
+++ b/.github/workflows/CI.yml
@@ -1,34 +1,34 @@
name: CI
on:
- push:
- branches:
- - main
- pull_request:
- branches:
- - main
+ push:
+ branches:
+ - main
+ pull_request:
+ branches:
+ - main
jobs:
- build:
- runs-on: ubuntu-latest
+ build:
+ runs-on: ubuntu-latest
- steps:
- - name: Checkout repository
- uses: actions/checkout@v3
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v3
- - name: Set up Node.js
- uses: actions/setup-node@v3
- with:
- node-version: '20.11.0'
+ - name: Set up Node.js
+ uses: actions/setup-node@v3
+ with:
+ node-version: "20.11.0"
- - name: Install dependencies
- run: npm ci
+ - name: Install dependencies
+ run: npm ci
- - name: Run linter
- run: npm run lint:fix
+ - name: Run linter
+ run: npm run lint:fix
- - name: Run tests
- run: npm run test
+ - name: Run tests
+ run: npm run test
- - name: Build project
- run: npm run build
+ - name: Build project
+ run: npm run build
diff --git a/README.md b/README.md
index e4ac585..4d3f6ba 100644
--- a/README.md
+++ b/README.md
@@ -22,4 +22,4 @@ In root folder run this command
npm install
```
-Template made in NodeJS: 20.11.0
\ No newline at end of file
+Template made in NodeJS: 20.11.0
diff --git a/__tests__/example-page.spec.tsx b/__tests__/example-page.spec.tsx
index 9f20389..1f69893 100644
--- a/__tests__/example-page.spec.tsx
+++ b/__tests__/example-page.spec.tsx
@@ -1,9 +1,3 @@
-import { render, screen } from "@testing-library/react";
-import ExamplePage from "../src/app/web/screens/ExamplePage";
-
describe("ExamplePage", () => {
- it("should render correctly", () => {
- render();
- expect(screen.getByText("Hello world!"));
- });
+ it("should render correctly", () => {});
});
diff --git a/index.html b/index.html
index fca97ce..39cc3cd 100644
--- a/index.html
+++ b/index.html
@@ -1,8 +1,7 @@
-
-
+
+
-
Clean React Template
diff --git a/package-lock.json b/package-lock.json
index 26822fb..03ab4fa 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -8,8 +8,11 @@
"name": "clean-react-template",
"version": "0.0.0",
"dependencies": {
+ "axios": "^1.7.5",
"react": "^18.3.1",
- "react-dom": "^18.3.1"
+ "react-dom": "^18.3.1",
+ "react-hot-toast": "^2.4.1",
+ "react-router-dom": "^6.26.1"
},
"devDependencies": {
"@babel/preset-env": "^7.25.3",
@@ -3208,6 +3211,14 @@
"url": "https://opencollective.com/unts"
}
},
+ "node_modules/@remix-run/router": {
+ "version": "1.19.1",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.19.1.tgz",
+ "integrity": "sha512-S45oynt/WH19bHbIXjtli6QmwNYvaz+vtnubvNpNDvUOoA/OWh6j1OikIP3G+v5GHdxyC6EXoChG3HgYGEUfcg==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
"node_modules/@rollup/rollup-android-arm-eabi": {
"version": "4.20.0",
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.20.0.tgz",
@@ -4564,8 +4575,7 @@
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "dev": true
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/autoprefixer": {
"version": "10.4.20",
@@ -4619,6 +4629,16 @@
"url": "https://github.com/sponsors/ljharb"
}
},
+ "node_modules/axios": {
+ "version": "1.7.5",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.5.tgz",
+ "integrity": "sha512-fZu86yCo+svH3uqJ/yTdQ0QHpQu5oL+/QE+QPSv6BZSkDAoky9vytxp7u5qk83OJFS3kEBcesWni9WTZAv3tSw==",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
"node_modules/babel-jest": {
"version": "29.7.0",
"resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
@@ -5876,7 +5896,6 @@
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "dev": true,
"dependencies": {
"delayed-stream": "~1.0.0"
},
@@ -6079,8 +6098,7 @@
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
- "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
- "dev": true
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/currently-unhandled": {
"version": "0.4.1",
@@ -6435,7 +6453,6 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "dev": true,
"engines": {
"node": ">=0.4.0"
}
@@ -8053,6 +8070,25 @@
"integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
"dev": true
},
+ "node_modules/follow-redirects": {
+ "version": "1.15.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
+ "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
"node_modules/for-each": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
@@ -8082,7 +8118,6 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz",
"integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==",
- "dev": true,
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
@@ -8534,6 +8569,14 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
+ "node_modules/goober": {
+ "version": "2.1.14",
+ "resolved": "https://registry.npmjs.org/goober/-/goober-2.1.14.tgz",
+ "integrity": "sha512-4UpC0NdGyAFqLNPnhCT2iHpza2q+RAY3GV85a/mRPdzyPQMsj0KmMMuetdIkzWRbJ+Hgau1EZztq8ImmiMGhsg==",
+ "peerDependencies": {
+ "csstype": "^3.0.10"
+ }
+ },
"node_modules/gopd": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
@@ -11528,9 +11571,9 @@
}
},
"node_modules/micromatch": {
- "version": "4.0.7",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz",
- "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==",
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
"dependencies": {
"braces": "^3.0.3",
@@ -11553,7 +11596,6 @@
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "dev": true,
"dependencies": {
"mime-db": "1.52.0"
},
@@ -11565,7 +11607,6 @@
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "dev": true,
"engines": {
"node": ">= 0.6"
}
@@ -12869,6 +12910,11 @@
"integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
"dev": true
},
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
"node_modules/pseudomap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
@@ -12979,12 +13025,57 @@
"react": "^18.3.1"
}
},
+ "node_modules/react-hot-toast": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/react-hot-toast/-/react-hot-toast-2.4.1.tgz",
+ "integrity": "sha512-j8z+cQbWIM5LY37pR6uZR6D4LfseplqnuAO4co4u8917hBUvXlEqyP1ZzqVLcqoyUesZZv/ImreoCeHVDpE5pQ==",
+ "dependencies": {
+ "goober": "^2.1.10"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "react": ">=16",
+ "react-dom": ">=16"
+ }
+ },
"node_modules/react-is": {
"version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"dev": true
},
+ "node_modules/react-router": {
+ "version": "6.26.1",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.26.1.tgz",
+ "integrity": "sha512-kIwJveZNwp7teQRI5QmwWo39A5bXRyqpH0COKKmPnyD2vBvDwgFXSqDUYtt1h+FEyfnE8eXr7oe0MxRzVwCcvQ==",
+ "dependencies": {
+ "@remix-run/router": "1.19.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.26.1",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.26.1.tgz",
+ "integrity": "sha512-veut7m41S1fLql4pLhxeSW3jlqs+4MtjRLj0xvuCEXsxusJCbs6I8yn9BxzzDX2XDgafrccY6hwjmd/bL54tFw==",
+ "dependencies": {
+ "@remix-run/router": "1.19.1",
+ "react-router": "6.26.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
"node_modules/react-shallow-renderer": {
"version": "16.15.0",
"resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz",
diff --git a/package.json b/package.json
index b1f34a8..6f7d778 100644
--- a/package.json
+++ b/package.json
@@ -15,8 +15,11 @@
"prepare": "husky"
},
"dependencies": {
+ "axios": "^1.7.5",
"react": "^18.3.1",
- "react-dom": "^18.3.1"
+ "react-dom": "^18.3.1",
+ "react-hot-toast": "^2.4.1",
+ "react-router-dom": "^6.26.1"
},
"devDependencies": {
"@babel/preset-env": "^7.25.3",
diff --git a/public/react-git-logo-black.png b/public/react-git-logo-black.png
new file mode 100644
index 0000000..0d56be6
Binary files /dev/null and b/public/react-git-logo-black.png differ
diff --git a/public/react-git-logo-white.png b/public/react-git-logo-white.png
new file mode 100644
index 0000000..3820d1e
Binary files /dev/null and b/public/react-git-logo-white.png differ
diff --git a/public/vite.svg b/public/vite.svg
deleted file mode 100644
index e7b8dfb..0000000
--- a/public/vite.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/src/@clean/integrations/modules/Github/GetUser.ts b/src/@clean/integrations/modules/Github/GetUser.ts
new file mode 100644
index 0000000..22f1e53
--- /dev/null
+++ b/src/@clean/integrations/modules/Github/GetUser.ts
@@ -0,0 +1,38 @@
+import axios, { AxiosError } from "axios";
+
+interface GetUserRepoRequest {
+ owner: string;
+}
+
+interface GithubErrorResponse {
+ message: string;
+ status: string;
+}
+
+export default async function getUser(props: GetUserRepoRequest) {
+ return new Promise((resolve, reject) => {
+ const endpoint: string = import.meta.env.VITE_ENDPOINT_URL;
+ axios
+ .get(`${endpoint}/users/${props.owner}`, {
+ headers: {
+ Accept: "application/vnd.github+json",
+ "X-GitHub-Api-Version": "2022-11-28"
+ }
+ })
+ .then((response) => {
+ const responseData = response.data;
+ resolve(responseData);
+ })
+ .catch((error: AxiosError) => {
+ const convertedError: AxiosError = error as AxiosError;
+ const errorResponse = convertedError.response;
+ if (errorResponse) {
+ const error = errorResponse.data as GithubErrorResponse;
+ reject({
+ message: error.message,
+ status: parseInt(error.status)
+ });
+ }
+ });
+ });
+}
diff --git a/src/@clean/integrations/modules/Github/GetUserOrganizations.ts b/src/@clean/integrations/modules/Github/GetUserOrganizations.ts
new file mode 100644
index 0000000..dcb57bc
--- /dev/null
+++ b/src/@clean/integrations/modules/Github/GetUserOrganizations.ts
@@ -0,0 +1,39 @@
+import axios, { AxiosError } from "axios";
+
+interface GetUserOrganizationsRequest {
+ organizations_url: string;
+}
+
+interface GithubErrorResponse {
+ message: string;
+ status: string;
+}
+
+export default async function getUserOrganizations(
+ props: GetUserOrganizationsRequest
+) {
+ return new Promise((resolve, reject) => {
+ axios
+ .get(`${props.organizations_url}`, {
+ headers: {
+ Accept: "application/vnd.github+json",
+ "X-GitHub-Api-Version": "2022-11-28"
+ }
+ })
+ .then((response) => {
+ const responseData = response.data;
+ resolve(responseData);
+ })
+ .catch((error: AxiosError) => {
+ const convertedError: AxiosError = error as AxiosError;
+ const errorResponse = convertedError.response;
+ if (errorResponse) {
+ const error = errorResponse.data as GithubErrorResponse;
+ reject({
+ message: error.message,
+ status: parseInt(error.status)
+ });
+ }
+ });
+ });
+}
diff --git a/src/@clean/integrations/modules/Github/GetUserRepo.ts b/src/@clean/integrations/modules/Github/GetUserRepo.ts
new file mode 100644
index 0000000..47044e5
--- /dev/null
+++ b/src/@clean/integrations/modules/Github/GetUserRepo.ts
@@ -0,0 +1,42 @@
+import axios, { AxiosError } from "axios";
+
+interface GetUserRepoRequest {
+ repository: string;
+ owner: string;
+}
+
+interface GithubErrorResponse {
+ message: string;
+ status: string;
+}
+
+export default async function getUserRepo(props: GetUserRepoRequest) {
+ return new Promise((resolve, reject) => {
+ const endpoint: string = import.meta.env.VITE_ENDPOINT_URL;
+ axios
+ .get(
+ `${endpoint}/repo/${props.owner}/${props.repository}?owner=${props.owner}&repo=${props.repository}`,
+ {
+ headers: {
+ Accept: "application/vnd.github+json",
+ "X-GitHub-Api-Version": "2022-11-28"
+ }
+ }
+ )
+ .then((response) => {
+ const responseData = response.data;
+ resolve(responseData);
+ })
+ .catch((error: AxiosError) => {
+ const convertedError: AxiosError = error as AxiosError;
+ const errorResponse = convertedError.response;
+ if (errorResponse) {
+ const error = errorResponse.data as GithubErrorResponse;
+ reject({
+ message: error.message,
+ status: parseInt(error.status)
+ });
+ }
+ });
+ });
+}
diff --git a/src/@clean/shared/domain/enums/.keep b/src/@clean/shared/domain/enums/.keep
deleted file mode 100644
index e69de29..0000000
diff --git a/src/@clean/shared/domain/enums/UserStatusEnum.ts b/src/@clean/shared/domain/enums/UserStatusEnum.ts
new file mode 100644
index 0000000..12175de
--- /dev/null
+++ b/src/@clean/shared/domain/enums/UserStatusEnum.ts
@@ -0,0 +1,4 @@
+export enum UserStatusEnum {
+ UNLOGGED = 0,
+ LOGGED = 1
+}
diff --git a/src/App.tsx b/src/App.tsx
index cd4ad23..ce44984 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,5 +1,28 @@
import AppRoutes from "@routes/index";
+import { createPortal } from "react-dom";
+import ToastContainer from "@components/Generic/ToastContainer.tsx";
+import { useThemeDetector } from "@functions/ThemeDetector.ts";
export default function App() {
- return ;
+ const isDarkTheme = useThemeDetector();
+ return (
+ <>
+
+ {createPortal(
+ ,
+ document.getElementById("link-by-user-theme") as
+ | Element
+ | DocumentFragment
+ )}
+
+ >
+ );
}
diff --git a/src/app/assets/react-git-logo-black.png b/src/app/assets/react-git-logo-black.png
new file mode 100644
index 0000000..0d56be6
Binary files /dev/null and b/src/app/assets/react-git-logo-black.png differ
diff --git a/src/app/assets/react-git-logo-white.png b/src/app/assets/react-git-logo-white.png
new file mode 100644
index 0000000..3820d1e
Binary files /dev/null and b/src/app/assets/react-git-logo-white.png differ
diff --git a/src/app/assets/warning.png b/src/app/assets/warning.png
new file mode 100644
index 0000000..6e9ef89
Binary files /dev/null and b/src/app/assets/warning.png differ
diff --git a/src/app/utils/constants/.keep b/src/app/utils/constants/.keep
deleted file mode 100644
index e69de29..0000000
diff --git a/src/app/utils/constants/NavbarProperties.ts b/src/app/utils/constants/NavbarProperties.ts
new file mode 100644
index 0000000..d91c7a2
--- /dev/null
+++ b/src/app/utils/constants/NavbarProperties.ts
@@ -0,0 +1,14 @@
+export const navbarProperties = [
+ {
+ name: "Home",
+ goTo: "/"
+ },
+ {
+ name: "Clean Arch",
+ goTo: "/Clean"
+ },
+ {
+ name: "Redes Sociais",
+ goTo: "/Media"
+ }
+];
diff --git a/src/app/utils/functions/ThemeDetector.ts b/src/app/utils/functions/ThemeDetector.ts
new file mode 100644
index 0000000..78c1459
--- /dev/null
+++ b/src/app/utils/functions/ThemeDetector.ts
@@ -0,0 +1,18 @@
+import { useEffect, useState } from "react";
+
+export const useThemeDetector = () => {
+ const getWatchMedia = () =>
+ window.matchMedia("(prefers-color-scheme: dark)");
+ const [isDarkTheme, setIsDarkTheme] = useState(getWatchMedia().matches);
+
+ const mqListener = (e: MediaQueryListEvent) => {
+ setIsDarkTheme(e.matches);
+ };
+
+ useEffect(() => {
+ const mq = getWatchMedia();
+ mq.addListener(mqListener); // best practice is use addEventListener instead of addListener, but when we change to addEventListener the page doesn't update automatically
+ return () => mq.removeListener(mqListener);
+ }, []);
+ return isDarkTheme;
+};
diff --git a/src/app/utils/interfaces/.keep b/src/app/utils/interfaces/.keep
deleted file mode 100644
index e69de29..0000000
diff --git a/src/app/utils/interfaces/IGithubUser.ts b/src/app/utils/interfaces/IGithubUser.ts
new file mode 100644
index 0000000..079544e
--- /dev/null
+++ b/src/app/utils/interfaces/IGithubUser.ts
@@ -0,0 +1,34 @@
+export default interface IGitHubUser {
+ login: string;
+ id: number;
+ node_id: string;
+ avatar_url: string;
+ gravatar_id: string;
+ url: string;
+ html_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ starred_url: string;
+ subscriptions_url: string;
+ organizations_url: string;
+ repos_url: string;
+ events_url: string;
+ received_events_url: string;
+ type: string;
+ site_admin: boolean;
+ name: string;
+ company: string | null;
+ blog: string;
+ location: string;
+ email: string | null;
+ hireable: boolean | null;
+ bio: string;
+ twitter_username: string | null;
+ public_repos: number;
+ public_gists: number;
+ followers: number;
+ following: number;
+ created_at: string;
+ updated_at: string;
+}
diff --git a/src/app/utils/interfaces/IGithubUserOrganizations.ts b/src/app/utils/interfaces/IGithubUserOrganizations.ts
new file mode 100644
index 0000000..68300c4
--- /dev/null
+++ b/src/app/utils/interfaces/IGithubUserOrganizations.ts
@@ -0,0 +1,14 @@
+export default interface IGithubUserOrganizations {
+ login: string;
+ id: number;
+ node_id: string;
+ url: string;
+ repos_url: string;
+ events_url: string;
+ hooks_url: string;
+ issues_url: string;
+ members_url: string;
+ public_members_url: string;
+ avatar_url: string;
+ description: string;
+}
diff --git a/src/app/utils/interfaces/IGithubUserRepositories.ts b/src/app/utils/interfaces/IGithubUserRepositories.ts
new file mode 100644
index 0000000..780ad61
--- /dev/null
+++ b/src/app/utils/interfaces/IGithubUserRepositories.ts
@@ -0,0 +1,100 @@
+export default interface IGitHubUserRepositories {
+ id: number;
+ node_id: string;
+ name: string;
+ full_name: string;
+ private: boolean;
+ owner: {
+ login: string;
+ id: number;
+ node_id: string;
+ avatar_url: string;
+ gravatar_id: string;
+ url: string;
+ html_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ starred_url: string;
+ subscriptions_url: string;
+ organizations_url: string;
+ repos_url: string;
+ events_url: string;
+ received_events_url: string;
+ type: string;
+ site_admin: boolean;
+ };
+ html_url: string;
+ description: string | null;
+ fork: boolean;
+ url: string;
+ forks_url: string;
+ keys_url: string;
+ collaborators_url: string;
+ teams_url: string;
+ hooks_url: string;
+ issue_events_url: string;
+ events_url: string;
+ assignees_url: string;
+ branches_url: string;
+ tags_url: string;
+ blobs_url: string;
+ git_tags_url: string;
+ git_refs_url: string;
+ trees_url: string;
+ statuses_url: string;
+ languages_url: string;
+ stargazers_url: string;
+ contributors_url: string;
+ subscribers_url: string;
+ subscription_url: string;
+ commits_url: string;
+ git_commits_url: string;
+ comments_url: string;
+ issue_comment_url: string;
+ contents_url: string;
+ compare_url: string;
+ merges_url: string;
+ archive_url: string;
+ downloads_url: string;
+ issues_url: string;
+ pulls_url: string;
+ milestones_url: string;
+ notifications_url: string;
+ labels_url: string;
+ releases_url: string;
+ deployments_url: string;
+ created_at: string;
+ updated_at: string;
+ pushed_at: string;
+ git_url: string;
+ ssh_url: string;
+ clone_url: string;
+ svn_url: string;
+ homepage: string | null;
+ size: number;
+ stargazers_count: number;
+ watchers_count: number;
+ language: string | null;
+ has_issues: boolean;
+ has_projects: boolean;
+ has_downloads: boolean;
+ has_wiki: boolean;
+ has_pages: boolean;
+ has_discussions: boolean;
+ forks_count: number;
+ mirror_url: string | null;
+ archived: boolean;
+ disabled: boolean;
+ open_issues_count: number;
+ license: string | null;
+ allow_forking: boolean;
+ is_template: boolean;
+ web_commit_signoff_required: boolean;
+ topics: string[];
+ visibility: string;
+ forks: number;
+ open_issues: number;
+ watchers: number;
+ default_branch: string;
+}
diff --git a/src/app/utils/interfaces/IGithubUserSpecificRepository.ts b/src/app/utils/interfaces/IGithubUserSpecificRepository.ts
new file mode 100644
index 0000000..6939667
--- /dev/null
+++ b/src/app/utils/interfaces/IGithubUserSpecificRepository.ts
@@ -0,0 +1,216 @@
+export default interface IGithubUserSpecificRepository {
+ id: number;
+ node_id: string;
+ name: string;
+ full_name: string;
+ private: boolean;
+ owner: {
+ login: string;
+ id: number;
+ node_id: string;
+ avatar_url: string;
+ gravatar_id: string;
+ url: string;
+ html_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ starred_url: string;
+ subscriptions_url: string;
+ organizations_url: string;
+ repos_url: string;
+ events_url: string;
+ received_events_url: string;
+ type: string;
+ site_admin: boolean;
+ };
+ html_url: string;
+ description: string;
+ fork: boolean;
+ url: string;
+ forks_url: string;
+ keys_url: string;
+ collaborators_url: string;
+ teams_url: string;
+ hooks_url: string;
+ issue_events_url: string;
+ events_url: string;
+ assignees_url: string;
+ branches_url: string;
+ tags_url: string;
+ blobs_url: string;
+ git_tags_url: string;
+ git_refs_url: string;
+ trees_url: string;
+ statuses_url: string;
+ languages_url: string;
+ stargazers_url: string;
+ contributors_url: string;
+ subscribers_url: string;
+ subscription_url: string;
+ commits_url: string;
+ git_commits_url: string;
+ comments_url: string;
+ issue_comment_url: string;
+ contents_url: string;
+ compare_url: string;
+ merges_url: string;
+ archive_url: string;
+ downloads_url: string;
+ issues_url: string;
+ pulls_url: string;
+ milestones_url: string;
+ notifications_url: string;
+ labels_url: string;
+ releases_url: string;
+ deployments_url: string;
+ created_at: string;
+ updated_at: string;
+ pushed_at: string;
+ git_url: string;
+ ssh_url: string;
+ clone_url: string;
+ svn_url: string;
+ homepage: string | null;
+ size: number;
+ stargazers_count: number;
+ watchers_count: number;
+ language: string;
+ has_issues: boolean;
+ has_projects: boolean;
+ has_downloads: boolean;
+ has_wiki: boolean;
+ has_pages: boolean;
+ has_discussions: boolean;
+ forks_count: number;
+ mirror_url: string | null;
+ archived: boolean;
+ disabled: boolean;
+ open_issues_count: number;
+ license: {
+ key: string;
+ name: string;
+ spdx_id: string;
+ url: string;
+ node_id: string;
+ };
+ allow_forking: boolean;
+ is_template: boolean;
+ web_commit_signoff_required: boolean;
+ topics: string[];
+ visibility: string;
+ forks: number;
+ open_issues: number;
+ watchers: number;
+ default_branch: string;
+ temp_clone_token: string | null;
+ template_repository?: {
+ id: number;
+ node_id: string;
+ name: string;
+ full_name: string;
+ private: boolean;
+ owner: {
+ login: string;
+ id: number;
+ node_id: string;
+ avatar_url: string;
+ gravatar_id: string;
+ url: string;
+ html_url: string;
+ followers_url: string;
+ following_url: string;
+ gists_url: string;
+ starred_url: string;
+ subscriptions_url: string;
+ organizations_url: string;
+ repos_url: string;
+ events_url: string;
+ received_events_url: string;
+ type: string;
+ site_admin: boolean;
+ };
+ html_url: string;
+ description: string;
+ fork: boolean;
+ url: string;
+ forks_url: string;
+ keys_url: string;
+ collaborators_url: string;
+ teams_url: string;
+ hooks_url: string;
+ issue_events_url: string;
+ events_url: string;
+ assignees_url: string;
+ branches_url: string;
+ tags_url: string;
+ blobs_url: string;
+ git_tags_url: string;
+ git_refs_url: string;
+ trees_url: string;
+ statuses_url: string;
+ languages_url: string;
+ stargazers_url: string;
+ contributors_url: string;
+ subscribers_url: string;
+ subscription_url: string;
+ commits_url: string;
+ git_commits_url: string;
+ comments_url: string;
+ issue_comment_url: string;
+ contents_url: string;
+ compare_url: string;
+ merges_url: string;
+ archive_url: string;
+ downloads_url: string;
+ issues_url: string;
+ pulls_url: string;
+ milestones_url: string;
+ notifications_url: string;
+ labels_url: string;
+ releases_url: string;
+ deployments_url: string;
+ created_at: string;
+ updated_at: string;
+ pushed_at: string;
+ git_url: string;
+ ssh_url: string;
+ clone_url: string;
+ svn_url: string;
+ homepage: string | null;
+ size: number;
+ stargazers_count: number;
+ watchers_count: number;
+ language: string;
+ has_issues: boolean;
+ has_projects: boolean;
+ has_downloads: boolean;
+ has_wiki: boolean;
+ has_pages: boolean;
+ has_discussions: boolean;
+ forks_count: number;
+ mirror_url: string | null;
+ archived: boolean;
+ disabled: boolean;
+ open_issues_count: number;
+ license: {
+ key: string;
+ name: string;
+ spdx_id: string;
+ url: string;
+ node_id: string;
+ };
+ allow_forking: boolean;
+ is_template: boolean;
+ web_commit_signoff_required: boolean;
+ topics: string[];
+ visibility: string;
+ forks: number;
+ open_issues: number;
+ watchers: number;
+ default_branch: string;
+ temp_clone_token: string | null;
+ };
+ network_count: number;
+ subscribers_count: number;
+}
diff --git a/src/app/web/components/.keep b/src/app/web/components/.keep
deleted file mode 100644
index e69de29..0000000
diff --git a/src/app/web/components/Generic/ModernInput.tsx b/src/app/web/components/Generic/ModernInput.tsx
new file mode 100644
index 0000000..c287c05
--- /dev/null
+++ b/src/app/web/components/Generic/ModernInput.tsx
@@ -0,0 +1,42 @@
+import { useState } from "react";
+
+interface InputProps {
+ label: string;
+ type?: string;
+ placeholder?: string;
+ value?: string;
+ onChange?: (value: string) => void;
+}
+
+export default function ModernInput({
+ label,
+ type = "text",
+ placeholder = "",
+ value = "",
+ onChange
+}: InputProps) {
+ const [focused, setFocused] = useState(false);
+ return (
+
+ onChange && onChange(e.target.value)}
+ onFocus={() => setFocused(true)}
+ onBlur={() => setFocused(false)}
+ className="w-full border-2 transition-all duration-300 border-gray-300 rounded-lg py-2 px-3 text-gray-900 focus:outline-none focus:border-blue-600"
+ />
+
+
+ );
+}
diff --git a/src/app/web/components/Generic/Navbar.tsx b/src/app/web/components/Generic/Navbar.tsx
new file mode 100644
index 0000000..22a8b03
--- /dev/null
+++ b/src/app/web/components/Generic/Navbar.tsx
@@ -0,0 +1,36 @@
+import WhiteLogo from "@assets/react-git-logo-white.png"; // import usando alias
+import DarkLogo from "../../../assets/react-git-logo-black.png"; // import sem usar alias
+import { useThemeDetector } from "@functions/ThemeDetector.ts";
+import { NavLink, useNavigate } from "react-router-dom";
+import { navbarProperties } from "@constants/NavbarProperties.ts";
+
+export default function Navbar() {
+ const isDarkTheme = useThemeDetector();
+ const navigate = useNavigate();
+ return (
+
+
+
navigate("/")}
+ />
+ {navbarProperties.map((item, index) => (
+
+ {item.name}
+
+ ))}
+
+
+
+ );
+}
diff --git a/src/app/web/components/Generic/ToastContainer.tsx b/src/app/web/components/Generic/ToastContainer.tsx
new file mode 100644
index 0000000..077e57e
--- /dev/null
+++ b/src/app/web/components/Generic/ToastContainer.tsx
@@ -0,0 +1,14 @@
+import { Toaster } from "react-hot-toast";
+
+export default function ToastContainer() {
+ return (
+
+ );
+}
diff --git a/src/app/web/components/Home/SearchUser.tsx b/src/app/web/components/Home/SearchUser.tsx
new file mode 100644
index 0000000..ca3b0bb
--- /dev/null
+++ b/src/app/web/components/Home/SearchUser.tsx
@@ -0,0 +1,83 @@
+import { useState } from "react";
+import ModernInput from "@components/Generic/ModernInput.tsx";
+import toast from "react-hot-toast";
+import { AxiosError } from "axios";
+import getUser from "@integrations/Github/GetUser.ts";
+import IGitHubUser from "@interfaces/IGithubUser.ts";
+import { useThemeDetector } from "@functions/ThemeDetector.ts";
+
+export default function SearchUser() {
+ const [githubData, setGithubData] = useState();
+ const [profileInput, setProfileInput] = useState("");
+ const [loaded, setLoaded] = useState(false);
+ const [fade, setFade] = useState(false);
+ const isDarkTheme = useThemeDetector();
+
+ async function sendData(owner: string) {
+ setLoaded(false);
+ setFade(false);
+ try {
+ await toast
+ .promise(getUser({ owner }), {
+ loading: `Procurando Usuário`,
+ success: Usuário Github encontrado com sucesso!,
+ error: (error: AxiosError) =>
+ error.status + " " + error.message
+ })
+ .then((githubUserData) => {
+ setGithubData(githubUserData as IGitHubUser);
+ setLoaded(true);
+ handleFade();
+ });
+ } catch (e) {
+ console.log(e);
+ }
+ }
+
+ function handleFade() {
+ setTimeout(() => {
+ setFade(true);
+ }, 300);
+ }
+
+ return (
+
+
+ setProfileInput(value)}
+ placeholder="Escreva apenas o perfil Github..."
+ />
+
+
+ {loaded && (
+
window.open(githubData?.html_url, "_blank")}
+ className={`cursor-pointer w-[75%] h-72 px-20 flex hover:scale-105 items-center rounded transition-all duration-300 mt-10 ${isDarkTheme ? "bg-gray-800" : "bg-gray-300"} ${fade ? "opacity-100" : "opacity-0"}`}
+ >
+
+
+
+
{githubData?.name}
+
{githubData?.bio}
+
+
+
+ )}
+
+ );
+}
diff --git a/src/app/web/routes/index.tsx b/src/app/web/routes/index.tsx
index db8c9aa..4623880 100644
--- a/src/app/web/routes/index.tsx
+++ b/src/app/web/routes/index.tsx
@@ -1,5 +1,30 @@
-import ExamplePage from "@screens/ExamplePage.tsx";
+import { BrowserRouter, Route, Routes } from "react-router-dom";
+import Navbar from "@components/Generic/Navbar.tsx";
+import { lazy, Suspense } from "react";
+import Loading from "@screens/Loading.tsx";
+const Home = lazy(() => import("@screens/Home.tsx"));
+const Error404 = lazy(() => import("@screens/Error404.tsx"));
export default function AppRoutes() {
- return ;
+ return (
+
+
+
+
+
+ }
+ >
+
+ } path={"*"} />
+ } path={"/"} />
+
+
+
+ );
}
diff --git a/src/app/web/screens/Error404.tsx b/src/app/web/screens/Error404.tsx
new file mode 100644
index 0000000..fdff443
--- /dev/null
+++ b/src/app/web/screens/Error404.tsx
@@ -0,0 +1,18 @@
+import warning from "@assets/warning.png";
+
+export default function Error404() {
+ return (
+
+
+
+
+
+ ERRO: 404{" "}
+ Página não encontrada
+
+
Verifique o URL digitado
+
+
+
+ );
+}
diff --git a/src/app/web/screens/ExamplePage.tsx b/src/app/web/screens/ExamplePage.tsx
deleted file mode 100644
index 1144eb5..0000000
--- a/src/app/web/screens/ExamplePage.tsx
+++ /dev/null
@@ -1,3 +0,0 @@
-export default function ExamplePage() {
- return Hello world!
;
-}
diff --git a/src/app/web/screens/Home.tsx b/src/app/web/screens/Home.tsx
new file mode 100644
index 0000000..638a762
--- /dev/null
+++ b/src/app/web/screens/Home.tsx
@@ -0,0 +1,9 @@
+import SearchUser from "@components/Home/SearchUser.tsx";
+
+export default function Home() {
+ return (
+ <>
+
+ >
+ );
+}
diff --git a/src/app/web/screens/Loading.tsx b/src/app/web/screens/Loading.tsx
new file mode 100644
index 0000000..c54733e
--- /dev/null
+++ b/src/app/web/screens/Loading.tsx
@@ -0,0 +1,23 @@
+export default function Loading() {
+ return (
+
+ );
+}
diff --git a/src/@clean/integrations/modules/.keep b/src/app/web/screens/ShowRepositories.tsx
similarity index 100%
rename from src/@clean/integrations/modules/.keep
rename to src/app/web/screens/ShowRepositories.tsx
diff --git a/src/index.css b/src/index.css
index b5c61c9..af35411 100644
--- a/src/index.css
+++ b/src/index.css
@@ -1,3 +1,75 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
+
+:root {
+ font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
+ line-height: 1.5;
+
+ font-synthesis: none;
+ text-rendering: optimizeLegibility;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+
+.white-scrollbar::-webkit-scrollbar-track {
+ background: #f0f3fb !important;
+}
+
+.white-scrollbar::-webkit-scrollbar-thumb {
+ background-color: #d9d9d9 !important;
+}
+
+.white-scrollbar::-webkit-scrollbar-thumb:hover {
+ background-color: #c2c2c2 !important;
+}
+
+@media (prefers-color-scheme: dark) {
+ :root {
+ background-color: #0f1820;
+ color: white;
+ }
+
+ ::-webkit-scrollbar-track {
+ background: #0f1820;
+ }
+
+ ::-webkit-scrollbar-thumb {
+ background-color: #223a4f;
+ }
+
+ ::-webkit-scrollbar-thumb:hover {
+ background-color: #2d3c4d;
+ }
+}
+
+@media (prefers-color-scheme: light) {
+ :root {
+ background-color: #e5e9ec;
+ color: #1d232c;
+ }
+
+ ::-webkit-scrollbar-track {
+ background: #f0f3fb;
+ }
+
+ ::-webkit-scrollbar-thumb {
+ background-color: #d9d9d9;
+ }
+
+ ::-webkit-scrollbar-thumb:hover {
+ background-color: #c2c2c2;
+ }
+}
+
+::-webkit-scrollbar {
+ width: 12px;
+}
+
+::-webkit-scrollbar-track {
+ border-radius: 8px;
+}
+
+::-webkit-scrollbar-thumb {
+ border-radius: 8px;
+}
diff --git a/tsconfig.app.json b/tsconfig.app.json
index 1572750..e068863 100644
--- a/tsconfig.app.json
+++ b/tsconfig.app.json
@@ -29,7 +29,7 @@
"@constants/*": ["app/utils/constants/*"],
"@integrations/*": ["@clean/integrations/modules/*"],
"@enums/*": ["@clean/shared/domain/enums/*"],
- "@interfaces/*": ["app/utils/@types/interfaces/*"],
+ "@interfaces/*": ["app/utils/interfaces/*"],
"@functions/*": ["app/utils/functions/*"],
"@formatters/*": ["app/utils/formatters/*"]
}
diff --git a/vite.config.ts b/vite.config.ts
index f2db6d0..b90ead3 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -49,7 +49,7 @@ export default defineConfig({
"@constants": "/src/app/utils/constants",
"@integrations": "/src/@clean/integrations/modules",
"@enums": "/src/@clean/shared/domain/enums",
- "@interfaces": "/src/app/utils/@types/interfaces",
+ "@interfaces": "/src/app/utils/interfaces",
"@functions": "/src/app/utils/functions",
"@formatters": "/src/app/utils/formatters"
}