Skip to content

Commit

Permalink
feat: add tools
Browse files Browse the repository at this point in the history
  • Loading branch information
Krauzy committed Nov 2, 2024
1 parent 94459c5 commit 1e6120c
Show file tree
Hide file tree
Showing 30 changed files with 2,253 additions and 35 deletions.
6 changes: 6 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,19 @@
"@fortawesome/react-fontawesome": "^0.2.2",
"@radix-ui/react-dialog": "^1.1.1",
"@radix-ui/react-tooltip": "^1.1.2",
"@types/axios": "^0.14.0",
"@types/jsonwebtoken": "^9.0.7",
"axios": "^1.7.7",
"cheerio": "^1.0.0",
"class-variance-authority": "^0.7.0",
"clsx": "^2.1.1",
"jsonwebtoken": "^9.0.2",
"lucide-react": "^0.439.0",
"next": "14.2.8",
"portfolio": "file:",
"react": "^18",
"react-dom": "^18",
"showdown": "^2.1.0",
"styled-components": "^6.1.13",
"tailwind-merge": "^2.5.2",
"tailwindcss-animate": "^1.0.7",
Expand Down
230 changes: 230 additions & 0 deletions src/app/admin/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,230 @@
'use client'

import { useContext, useEffect, useState } from "react";
import { AdminContainer, AdminContent, AdminSubtitle, AdminTitle, AdminValuedContainer, AdminValuedRow, LabelSide, ValueSide } from "./styles";
import { ThemeContext } from "@/contexts/ThemeContext";
import getLocale from "@/config/data";

export default function Admin() {
const { locale } = useContext(ThemeContext);
const localeData = getLocale(locale);

const [ip, setIp] = useState<string | undefined>();
const [browser, setBrowser] = useState<string | undefined>();
const [browserVersion, setBrowserVersion] = useState<string | undefined>();
const [os, setOs] = useState<string | undefined>();
const [network, setNetwork] = useState<string | undefined>();
const [timezone, setTimezone] = useState<string | undefined>();
const [latitude, setLatitude] = useState<number | undefined>();
const [longitude, setLongitude] = useState<number | undefined>();
const [browserResolution, setBrowserResolution] = useState<string | undefined>();
const [screenResolution, setScreenResolution] = useState<string | undefined>();
const [language, setLanguage] = useState<string | undefined>();
const [cookies, setCookies] = useState<string | undefined>();
const [media, setMedia] = useState<string | undefined>();

useEffect(() => {
if (ip === undefined) {
fetch('https://api.ipify.org?format=json')
.then(response => response.json())
.then(data => {
setIp(data.ip);
})
.catch(error => console.error('Erro ao pegar o IP:', error));
}
}, [ip, setIp]);

useEffect(() => {
const userAgent = navigator.userAgent;

if (browser === undefined || browserVersion === undefined) {
if (userAgent.indexOf("Chrome") > -1) {
setBrowser('Google Chrome');
const match = userAgent.match(/Chrome\/(\d+)/);
if (match) {
setBrowserVersion(match[1]);
}
} else if (userAgent.indexOf("Firefox") > -1) {
setBrowser('Mozilla Firefox');
const match = userAgent.match(/Firefox\/(\d+)/);
if (match) {
setBrowserVersion(match[1]);
}
} else if (userAgent.indexOf("Safari") > -1 && userAgent.indexOf("Chrome") === -1) {
setBrowser('Safari');
const match = userAgent.match(/Version\/(\d+)/);
if (match) {
setBrowserVersion(match[1]);
}
} else if (userAgent.indexOf("Edge") > -1) {
setBrowser('Microsoft Edge');
const match = userAgent.match(/Edge\/(\d+)/);
if (match) {
setBrowserVersion(match[1]);
}
} else if (userAgent.indexOf("Opera") > -1 || userAgent.indexOf("OPR") > -1) {
setBrowser('Opera');
const match = userAgent.match(/OPR\/(\d+)/);
if (match) {
setBrowserVersion(match[1]);
}
} else if (userAgent.indexOf("MSIE") > -1) {
setBrowser('Internet Explorer');
const match = userAgent.match(/MSIE (\d+)/);
if (match) {
setBrowserVersion(match[1]);
}
} else {
setBrowser('-');
setBrowserVersion('-');
}
}
}, [browser, browserVersion, setBrowser]);

useEffect(() => {
if (os === undefined) {
const userAgent = navigator.userAgent;

if (userAgent.indexOf('Windows NT 10.0') !== -1) setOs('Windows 10');
if (userAgent.indexOf('Windows NT 6.3') !== -1) setOs('Windows 8.1');
if (userAgent.indexOf('Windows NT 6.2') !== -1) setOs('Windows 8');
if (userAgent.indexOf('Windows NT 6.1') !== -1) setOs('Windows 7');
if (userAgent.indexOf('Windows NT 6.0') !== -1) setOs('Windows Vista');
if (userAgent.indexOf('Windows NT 5.1') !== -1) setOs('Windows XP');
if (userAgent.indexOf('Mac OS X') !== -1) setOs('macOS');
if (userAgent.indexOf('Linux') !== -1) setOs('Linux');
if (/Android/.test(userAgent)) setOs('Android');
if (/iPhone|iPad|iPod/.test(userAgent)) setOs('iOS');
}

}, [os, setOs]);

useEffect(() => {
interface NetworkInformation {
effectiveType?: string;
}

if (network === undefined) {
const nav = navigator as any; // Tipagem para navegadores que suportam a API Network Information

if ('connection' in nav) {
const connection: NetworkInformation = nav.connection || nav.mozConnection || nav.webkitConnection;
if (connection && connection.effectiveType) {
setNetwork(connection.effectiveType);
}
}
setNetwork('-');
}
}, [network]);

useEffect(() => {
if (timezone === undefined) {
setTimezone(Intl.DateTimeFormat().resolvedOptions().timeZone);
}
}, [timezone]);

useEffect(() => {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(
(position: GeolocationPosition) => {
setLongitude(position.coords.longitude);
setLatitude(position.coords.latitude);
},
(error: GeolocationPositionError) => {
console.error(`Error getting location: ${error.message}`);
}
);
} else {
console.error('Geolocation is not supported by this browser.');
}
}, [latitude, longitude]);

useEffect(() => {
if (browserResolution === undefined) {
setBrowserResolution(`${window.innerWidth}px X ${window.innerHeight}px`)
}
}, [browserResolution]);

useEffect(() => {
if (screenResolution === undefined) {
setScreenResolution(`${window.screen.width}px X ${window.screen.height}px`);
}
}, [screenResolution]);

useEffect(() => {
if (language === undefined) {
setLanguage(navigator.language);
}
}, [language]);

useEffect(() => {
if (cookies === undefined) {
setCookies(document.cookie === '' ? '-' : document.cookie.split(';').length.toString());
}
}, [cookies]);

return (
<AdminContainer>
<AdminContent>
<AdminTitle>{localeData.admin.title}</AdminTitle>
<AdminSubtitle>{localeData.admin.subtitle}</AdminSubtitle>
<AdminValuedContainer>
<AdminValuedRow>
<LabelSide>{localeData.admin.ip}</LabelSide>
<ValueSide>{ip}</ValueSide>
</AdminValuedRow>
<AdminValuedRow>
<LabelSide>{localeData.admin.browser}</LabelSide>
<ValueSide>{browser}</ValueSide>
</AdminValuedRow>
<AdminValuedRow>
<LabelSide>{localeData.admin.browserVersion}</LabelSide>
<ValueSide>v{browserVersion}</ValueSide>
</AdminValuedRow>
<AdminValuedRow>
<LabelSide>{localeData.admin.os}</LabelSide>
<ValueSide>{os}</ValueSide>
</AdminValuedRow>
<AdminValuedRow>
<LabelSide>{localeData.admin.networkProvider}</LabelSide>
<ValueSide>{network}</ValueSide>
</AdminValuedRow>
<AdminValuedRow>
<LabelSide>{localeData.admin.timeZone}</LabelSide>
<ValueSide>{timezone}</ValueSide>
</AdminValuedRow>
{latitude && longitude &&
<AdminValuedRow>
<LabelSide>{localeData.admin.location}</LabelSide>
<ValueSide href={`https://www.google.com.br/maps/@${latitude},${longitude},16z`} target="_blank">{'Map'}</ValueSide>
</AdminValuedRow>}
<AdminValuedRow>
<LabelSide>{localeData.admin.resolution}</LabelSide>
<ValueSide>{browserResolution}</ValueSide>
</AdminValuedRow>
<AdminValuedRow>
<LabelSide>{localeData.admin.screen}</LabelSide>
<ValueSide>{screenResolution}</ValueSide>
</AdminValuedRow>
<AdminValuedRow>
<LabelSide>{localeData.admin.language}</LabelSide>
<ValueSide>{language}</ValueSide>
</AdminValuedRow>
<AdminValuedRow>
<LabelSide>{localeData.admin.cookies}</LabelSide>
<ValueSide>{cookies}</ValueSide>
</AdminValuedRow>
<AdminValuedRow>
<LabelSide>{localeData.admin.processors}</LabelSide>
<ValueSide>{navigator.hardwareConcurrency.toString()}</ValueSide>
</AdminValuedRow>
<AdminValuedRow>
<LabelSide>{localeData.admin.javascript}</LabelSide>
<ValueSide>{'✅'}</ValueSide>
</AdminValuedRow>
</AdminValuedContainer>

</AdminContent>
</AdminContainer>
)
}
76 changes: 76 additions & 0 deletions src/app/admin/styles.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import styled from "styled-components";

export const AdminContainer = styled.div`
width: 100vw;
height: 100vh;
display: flex;
align-items: center;
justify-content: center;
`;

export const AdminContent = styled.div`
display: flex;
flex-direction: column;
align-items: center;
width: 80%;
`;

export const AdminTitle = styled.span`
font-family: ${props => props.theme.fonts.spaceMono};
font-size: 5em;
font-weight: 700;
color: ${props => props.theme.color.purple};
letter-spacing: 5px;
`;

export const AdminSubtitle = styled.p`
font-family: ${props => props.theme.fonts.spaceMono};
color: ${props => props.theme.color.variation.secondary(.8)};
text-align: center;
letter-spacing: 1px;
font-size: .8em;
`;

export const AdminValuedContainer = styled.div`
display: flex;
flex-direction: column;
margin-top: 2em;
width: 100%;
max-width: 30em;
gap: .7em;
`;

export const AdminValuedRow = styled.div`
width: 100%;
display: flex;
gap: 1em;
`;

export const LabelSide = styled.span`
width: 50%;
display: flex;
align-items: center;
justify-content: right;
color: ${props => props.theme.color.secondary};
font-family: ${props => props.theme.fonts.spaceMono};
font-weight: 600;
font-size: 1em;
@media screen and (max-width: 1100px) {
font-size: .8em;
}
`;

export const ValueSide = styled.a`
width: 50%;
display: flex;
color: ${props => props.theme.color.pink};
font-family: ${props => props.theme.fonts.spaceMono};
font-size: 1em;
${props => props.href && `text-decoration: underline`};
@media screen and (max-width: 1100px) {
font-size: .8em;
}
`;
13 changes: 12 additions & 1 deletion src/app/api/authentication/route.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
export async function POST(request: Request) {
export async function POST(req: Request) {
const body = await req.json();

const login = body['login'];
const password = body['password'];

if (login === process.env.ADMIN_EMAIL && password === process.env.ADMIN_ACCESS_KEY) {
return Response.json({
accessToken: process.env.JWT_SECRET_TOKEN
});
} else {
return Response.json({ }, { status: 401});
}
}
19 changes: 19 additions & 0 deletions src/app/api/proxy/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import axios from "axios";

export async function GET(req: Request) {
const { searchParams } = new URL(req.url);

const url = searchParams.get('url');

if (!url) {
return Response.json({ error: "URL is required!" }, { status: 404 });
}

try {
const response = await axios.get(url);
return Response.json(response.data, { status: 200 });
} catch (error: any) {
console.log(error.response.data);
return Response.json(error.response.data, { status: 200 });
}
}
7 changes: 5 additions & 2 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,22 @@ import GlobalLayout from "@/layout/global";
import "@/layout/globals.css";
import { cn } from "@/lib/utils"
import StyledComponentsRegistry from "./registry";
import LoadingContextProvider from "@/contexts/LoadingContext";

export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<html lang="en" suppressHydrationWarning={true}>
<body className={cn(`antialiased font-sans`)}>
<ThemeContextProvider>
<GlobalLayout>
<StyledComponentsRegistry>
{children}
<LoadingContextProvider>
{children}
</LoadingContextProvider>
</StyledComponentsRegistry>
</GlobalLayout>
</ThemeContextProvider>
Expand Down
Loading

0 comments on commit 1e6120c

Please sign in to comment.