remove unnecessary files

This commit is contained in:
2025-05-26 08:59:28 -03:00
parent 002705864b
commit d23b3887cc
50 changed files with 12 additions and 9869 deletions

View File

@@ -2,9 +2,9 @@
### Relacionamentos
Toda compra feita é relacionada com a empresa responsável, que é definida como o `tenant` da compra. Essa relação é estabelecida com base no CNPJ presente na compra.
Toda compra é relacionada a empresa responsável, que é definida como o `tenant` da mesma. Essa relação é estabelecida com base no CNPJ presente na compra.
O gestor responsável pela ação também é relacionado à compra.
O gestor responsável pela ação também é relacionado à compra, com base no email presente na compra.
```json
{"id": "10", "sk": "0", "metadata__tenant_id": "100", "metadata__related_ids": ["100", "123"]}
@@ -13,10 +13,18 @@ O gestor responsável pela ação também é relacionado à compra.
{"id": "10", "sk": "related_ids#user", "user_id": "123"}
```
# Usuários
# Matrículas
### Eventos agendados
Quando uma matrícula é criada, também é agendados emails.
- `reminder_no_access_3_days` se o usuário não acessar o curso 3 dias após a criação.
- `no_activity_7_days` 7 dias após a última atividade do usuário no curso.
- `access_period_reminder_30_days` 30 dias antes do acesso ao curso finalizar.
### Proteção contra duplicação
### Política de cancelamento
@@ -29,3 +37,5 @@ Apenas matrículas com `metadata#cancel_policy` podem ser canceladas.
```
### Relacionamentos
# Cursos

View File

@@ -1,4 +0,0 @@
.react-router
build
node_modules
README.md

View File

@@ -1,7 +0,0 @@
.DS_Store
/node_modules/
# React Router
/.react-router/
/build/
.env.local

View File

@@ -1,5 +0,0 @@
{
"semi": false,
"singleQuote": true,
"jsxSingleQuote": false
}

View File

@@ -1,22 +0,0 @@
FROM node:20-alpine AS development-dependencies-env
COPY . /app
WORKDIR /app
RUN npm ci
FROM node:20-alpine AS production-dependencies-env
COPY ./package.json package-lock.json /app/
WORKDIR /app
RUN npm ci --omit=dev
FROM node:20-alpine AS build-env
COPY . /app/
COPY --from=development-dependencies-env /app/node_modules /app/node_modules
WORKDIR /app
RUN npm run build
FROM node:20-alpine
COPY ./package.json package-lock.json /app/
COPY --from=production-dependencies-env /app/node_modules /app/node_modules
COPY --from=build-env /app/build /app/build
WORKDIR /app
CMD ["npm", "run", "start"]

View File

@@ -1,98 +0,0 @@
# Welcome to React Router!
A modern, production-ready template for building full-stack React applications using React Router.
## Features
- 🚀 Server-side rendering
- ⚡️ Hot Module Replacement (HMR)
- 📦 Asset bundling and optimization
- 🔄 Data loading and mutations
- 🔒 TypeScript by default
- 🎉 TailwindCSS for styling
- 📖 [React Router docs](https://reactrouter.com/)
## Getting Started
### Installation
Install the dependencies:
```bash
npm install
```
### Development
Start the development server with HMR:
```bash
npm run dev
```
Your application will be available at `http://localhost:5173`.
## Building for Production
Create a production build:
```bash
npm run build
```
## Deployment
### Docker Deployment
This template includes three Dockerfiles optimized for different package managers:
- `Dockerfile` - for npm
- `Dockerfile.pnpm` - for pnpm
- `Dockerfile.bun` - for bun
To build and run using Docker:
```bash
# For npm
docker build -t my-app .
# For pnpm
docker build -f Dockerfile.pnpm -t my-app .
# For bun
docker build -f Dockerfile.bun -t my-app .
# Run the container
docker run -p 3000:3000 my-app
```
The containerized application can be deployed to any platform that supports Docker, including:
- AWS ECS
- Google Cloud Run
- Azure Container Apps
- Digital Ocean App Platform
- Fly.io
- Railway
### DIY Deployment
If you're familiar with deploying Node applications, the built-in app server is production-ready.
Make sure to deploy the output of `npm run build`
```
├── package.json
├── package-lock.json (or pnpm-lock.yaml, or bun.lockb)
├── build/
│ ├── client/ # Static assets
│ └── server/ # Server-side code
```
## Styling
This template comes with [Tailwind CSS](https://tailwindcss.com/) already configured for a simple default starting experience. You can use whatever CSS framework you prefer.
---
Built with ❤️ using React Router.

View File

@@ -1,11 +0,0 @@
{
"Auth": {
"Cognito": {
"userPoolId": "sa-east-1_s6YmVSfXj",
"userPoolClientId": "ldfvdvkt6cl22n7p33vqtsf4j",
"loginWith": {
"email": true
}
}
}
}

View File

@@ -1,29 +0,0 @@
@import 'tailwindcss';
@theme {
--font-sans:
'Roboto', ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji',
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
--color-yellow-primary: #ffcf82;
--color-yellow-secondary: #f2ebe1;
--color-yellow-terciary: #f9f7e8;
--color-green-primary: #2e3524;
--color-green-secondary: #8cd366;
--color-green-terciary: #83926d;
--color-green-support: #c9fcad;
--color-green-pastel: #f9fff6;
--color-green-light: #cad9b4;
--color-green-dark: #4e8630;
}
html,
body {
@apply text-black dark:text-white;
@apply bg-gray-50/50 dark:bg-gray-900;
@media (prefers-color-scheme: dark) {
color-scheme: dark;
}
}

View File

@@ -1,25 +0,0 @@
import axios from 'axios'
const instance = axios.create({
baseURL: import.meta.env.VITE_API_URL,
})
instance.interceptors.response.use(
// Any status code that lie within the range of 2xx cause this function to trigger
function (response) {
return response
},
// Any status codes that falls outside the range of 2xx cause this function to trigger
function ({ response }) {
const error = new Error(response.data?.message)
error.code = response.data?.__type
error.name = response.data?.__type
error.statusCode = response.status
return Promise.reject(error)
},
)
export default instance

View File

@@ -1,18 +0,0 @@
import clsx from 'clsx'
export function Container({ children, className }) {
return (
<div
className={clsx(
'group-[.is-minimized]:lg:w-10/12',
'group-[.is-minimized]:xl:w-8/12',
'group-[.is-minimized]:2xl:w-6/12',
'xl:w-4/6 2xl:w-3/5',
'mx-auto',
className,
)}
>
{children}
</div>
)
}

View File

@@ -1,143 +0,0 @@
import React, { createElement, forwardRef, useContext, useId } from 'react'
import { ExclamationCircleIcon } from '@heroicons/react/24/outline'
import { omit } from 'ramda'
import { Loader } from './loader'
import clsx from 'clsx'
const ControlContext = React.createContext({})
function ControlProvider({ children, ...props }) {
return (
<ControlContext.Provider value={props}>{children}</ControlContext.Provider>
)
}
function useControl(props) {
const field = useContext(ControlContext)
return { ...field, ...props }
}
export const Control = forwardRef(function Control(
{ as = 'div', children, ...props },
ref,
) {
const id = useId()
const props_ = omit(['id'], props)
return (
<ControlProvider id={props?.id || id} {...props_}>
{React.createElement(as, { ref, ...props }, children)}
</ControlProvider>
)
})
export function Button({
children,
as = 'button',
className,
isLoading = false,
...props
}) {
if (isLoading) {
props['disabled'] = isLoading
}
return createElement(
as,
{
className: clsx(
'font-medium text-green-primary rounded-lg bg-green-secondary hover:bg-green-support',
'h-12 px-4 relative',
'disabled:bg-green-secondary/50 disabled:pointer-events-none',
'transition',
className,
),
...props,
},
<>
{isLoading && (
<div className="absolute inset-0 flex items-center justify-center bg-green-secondary rounded-xl">
<Loader className="w-5 text-white" />
</div>
)}
{children}
</>,
)
}
export function Label({ children, className, ...props }) {
const { id, htmlFor, className: _, ...field } = useControl(props)
return (
<label
className={clsx(
"black cursor-pointer aria-required:after:content-['*'] aria-required:after:ml-0.5 aria-required:after:text-red-500",
className,
)}
htmlFor={htmlFor ?? id}
{...field}
>
{children}
</label>
)
}
export const Input = forwardRef(function Input(
{ as = 'input', size = 'base', className, children, ...props },
ref,
) {
const { className: _, ...field } = useControl(props)
const sizes = { base: 'h-12' }
return createElement(
as,
{
className: clsx(
'bg-white outline-none px-4 rounded-lg transition',
'border border-green-light dark:border-gray-700 dark:bg-gray-800',
'focus:ring-1 focus:border-green-secondary focus:ring-green-secondary focus:placeholder:text-transparent',
'aria-[invalid=true]:border-red-400 aria-[invalid=true]:ring-red-400',
'dark:aria-[invalid=true]:border-red-500 dark:aria-[invalid=true]:ring-red-500',
'disabled:text-gray-400 disabled:border-gray-300 disabled:bg-gray-200',
'dark:disabled:text-gray-500 dark:disabled:bg-gray-700',
sizes?.[size],
className,
),
ref,
...field,
},
children,
)
})
export const Checkbox = forwardRef(function Checkbox(
{ className, ...props },
ref,
) {
const { className: _, ...field } = useControl(props)
return (
<input
type="checkbox"
className={clsx(
// 'text-green-secondary border border-gray-300',
// 'focus:ring-2 focus:border-green-secondary focus:ring-green-secondary focus:ring-offset-0 focus:ring-opacity-30',
// 'dark:border-gray-700 dark:bg-gray-800 focus:dark:border-security dark:checked:bg-green-secondary dark:checked:border-security dark:disabled:bg-gray-700',
// 'disabled:bg-gray-200 outline-none rounded transition',
className,
)}
ref={ref}
{...field}
/>
)
})
export function Error({ children }) {
return (
<div className="text-sm text-red-500 flex items-start gap-0.5">
<ExclamationCircleIcon className="w-4 mt-[1.5px] flex-shrink-0" />
<div>{children}</div>
</div>
)
}

View File

@@ -1,11 +0,0 @@
import clsx from 'clsx'
import React from 'react'
export function Heading({ as = 'h1', size = 'xl', className, children }) {
const sizes = { lg: 'text-lg lg:text-xl', xl: 'text-xl lg:text-2xl' }
return React.createElement(
as,
{ className: clsx('font-semibold', sizes?.[size], className) },
children,
)
}

View File

@@ -1,27 +0,0 @@
import clsx from 'clsx'
export function Loader({ className, ...props }) {
return (
<svg
className={clsx('animate-spin', className)}
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
{...props}
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
/>
<path
className="opacity-50"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
/>
</svg>
)
}

View File

@@ -1,99 +0,0 @@
export function Regular({ ...props }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 1072.73 329.6"
{...props}
>
<g>
<g>
<path
className="fill-green-secondary"
d="M152.18,217.62l-68.61-30.91c-1.88-1.2-4.28-1.2-6.16,0l-68.61,30.91c-3.81,2.43-8.8-.3-8.8-4.82V8.98C0,5.82,2.56,3.26,5.72,3.26h149.54c3.16,0,5.72,2.56,5.72,5.72v203.81c0,4.52-5,7.26-8.8,4.82Z"
/>
<path
className="fill-green-primary"
d="M93.97,74.01H26.61v20.16h67.36v-20.16Z"
/>
<path
className="fill-green-primary"
d="M107.44,111.16H26.61v26.8h80.83v-26.8Z"
/>
<path
className="fill-green-primary"
d="M107.44,30.27H26.61v26.8h80.83v-26.8Z"
/>
<path
className="fill-green-primary"
d="M134.38,131.23c0-3.72-3.02-6.73-6.73-6.73s-6.73,3.02-6.73,6.73,3.02,6.73,6.73,6.73,6.73-3.02,6.73-6.73Z"
/>
</g>
<g>
<path
className="fill-green-primary dark:fill-yellow-terciary"
d="M244.7,3.24h92.33v44.43h-44.15v88.85h39.38v39.62h-39.38v105.77h44.15v44.42h-92.33V3.24Z"
/>
<path
className="fill-green-primary dark:fill-yellow-terciary"
d="M362.72,3.24h57.79c10.71,0,20.47,2.35,29.29,7.06,8.83,4.7,15.79,11.18,20.87,19.39,5.08,8.21,7.63,17.45,7.63,27.67v214.88c0,10.22-2.48,19.46-7.42,27.67-4.96,8.21-11.83,14.69-20.68,19.39-8.83,4.7-18.73,7.08-29.7,7.08h-57.79V3.24ZM427.55,283.88c1.74-1.87,2.6-4.18,2.6-6.86V52.56c-.26-2.69-1.34-4.97-3.22-6.86-1.88-1.87-4.15-2.83-6.82-2.83h-14v243.85h14.41c2.93,0,5.27-.94,7.01-2.83h.02Z"
/>
<path
className="fill-green-primary dark:fill-yellow-terciary"
d="M531.5,322.49c-8.71-4.7-15.6-11.16-20.68-19.39-5.08-8.21-7.63-17.42-7.63-27.67V3.24h48.15v279.41c0,2.69.93,4.99,2.82,6.86,1.86,1.9,4.15,2.83,6.82,2.83,2.93,0,5.27-.94,7.01-2.83,1.74-1.87,2.6-4.18,2.6-6.86V3.24h48.16v272.21c0,10.25-2.48,19.46-7.42,27.67-4.96,8.21-11.83,14.69-20.68,19.39-8.85,4.7-18.73,7.08-29.7,7.08s-20.8-2.35-29.5-7.08l.05-.02Z"
/>
<path
className="fill-green-primary dark:fill-yellow-terciary"
d="M672.79,322.49c-8.7-4.7-15.6-11.16-20.68-19.39-5.08-8.21-7.63-17.42-7.63-27.67v-78.75h48.16v85.95c0,2.69.93,4.99,2.82,6.87,1.86,1.9,4.15,2.83,6.82,2.83,2.93,0,5.27-.94,7.01-2.83,1.74-1.87,2.6-4.18,2.6-6.87v-77.88c0-5.66-2.22-10.3-6.63-13.94-4.41-3.62-11.57-8.02-21.47-13.13-8.3-4.3-15.05-8.14-20.27-11.52-5.22-3.36-9.71-7.87-13.45-13.54-3.75-5.66-5.63-12.24-5.63-19.8V54.12c0-10.22,2.53-19.44,7.63-27.67,5.08-8.21,11.97-14.66,20.68-19.39,8.68-4.7,18.53-7.06,29.5-7.06s20.87,2.35,29.69,7.06c8.83,4.7,15.72,11.18,20.68,19.39,4.96,8.21,7.42,17.45,7.42,27.67v71.09h-48.16V46.92c0-2.69-.88-4.97-2.6-6.86-1.74-1.87-4.08-2.83-7.01-2.83-2.67,0-4.96.94-6.82,2.83-1.89,1.9-2.82,4.18-2.82,6.86v69.79c0,6.19,2.34,11.26,7.04,15.14,4.67,3.91,12.24,8.83,22.68,14.74,8.04,4.32,14.57,8.09,19.68,11.3,5.08,3.24,9.37,7.46,12.83,12.72,3.48,5.26,5.22,11.26,5.22,17.98v86.83c0,10.25-2.48,19.46-7.42,27.67-4.96,8.21-11.83,14.69-20.68,19.39-8.85,4.71-18.72,7.08-29.7,7.08s-20.8-2.35-29.5-7.08Z"
/>
<path
className="fill-green-primary dark:fill-yellow-terciary"
d="M784.56,3.24h92.33v44.43h-44.15v88.85h39.38v39.62h-39.38v105.77h44.15v44.42h-92.33V3.24Z"
/>
<path
className="fill-green-primary dark:fill-yellow-terciary"
d="M920.63,322.49c-5.63-4.18-10.11-10.1-13.45-17.76-3.34-7.68-5.01-16.49-5.01-26.45V53.71c0-9.96,2.53-19.06,7.63-27.26,5.08-8.21,12.05-14.66,20.87-19.39,8.83-4.7,18.6-7.06,29.32-7.06s20.54,2.35,29.5,7.06c8.97,4.7,15.91,11.18,20.87,19.39,4.96,8.21,7.42,17.3,7.42,27.26v94.51h-48.16V46.92c0-2.69-.88-4.97-2.6-6.86-1.74-1.87-4.08-2.83-7.01-2.83-2.67,0-4.96.94-6.82,2.83-1.89,1.9-2.82,4.18-2.82,6.86v231.36c0,2.69.93,4.99,2.82,6.87,1.86,1.9,4.15,2.83,6.82,2.83,2.93,0,5.27-.94,7.01-2.83,1.74-1.87,2.6-4.18,2.6-6.87v-46.03h-11.64v-51.29h59.8v145.4h-48.16v-14.14c-2.96,5.4-6.82,9.48-11.64,12.31-4.82,2.83-10.83,4.25-18.06,4.25s-13.64-2.09-19.27-6.26l-.02-.02Z"
/>
<path
className="fill-green-primary dark:fill-yellow-terciary"
d="M1053.27,25.05h-6.13l-.06-3.69h5.48c.83-.02,1.61-.15,2.33-.4.72-.27,1.3-.64,1.73-1.14.44-.51.65-1.14.65-1.87,0-.93-.16-1.67-.48-2.22-.3-.55-.83-.94-1.59-1.16-.74-.25-1.74-.37-3.01-.37h-3.78v20.42h-4.12V10.54h7.9c1.87,0,3.49.27,4.86.82,1.38.53,2.44,1.34,3.18,2.44.76,1.08,1.14,2.43,1.14,4.06,0,1.02-.24,1.93-.71,2.73-.47.8-1.17,1.49-2.1,2.07-.91.57-2.03,1.03-3.35,1.39-.06,0-.12.07-.2.2-.06.13-.11.2-.17.2-.32.19-.53.33-.63.43-.08.08-.16.12-.25.14-.08.02-.31.03-.68.03ZM1052.99,25.05l.6-2.81c2.95,0,4.97.64,6.05,1.93,1.08,1.27,1.62,2.89,1.62,4.86v1.53c0,.7.03,1.37.08,2.02.08.62.21,1.15.4,1.59v.45h-4.23c-.19-.49-.3-1.19-.34-2.1-.02-.91-.03-1.57-.03-1.99v-1.48c0-1.38-.31-2.39-.94-3.04s-1.69-.97-3.21-.97ZM1035.75,22.92c0,2.52.43,4.87,1.28,7.04.87,2.16,2.08,4.05,3.64,5.68,1.55,1.61,3.34,2.87,5.37,3.78,2.05.89,4.22,1.33,6.53,1.33s4.51-.44,6.53-1.33c2.03-.91,3.8-2.17,5.34-3.78,1.53-1.63,2.74-3.52,3.61-5.68.87-2.18,1.31-4.52,1.31-7.04s-.44-4.86-1.31-7.01c-.87-2.16-2.07-4.04-3.61-5.65-1.53-1.61-3.31-2.86-5.34-3.75-2.03-.91-4.2-1.36-6.53-1.36s-4.49.45-6.53,1.36c-2.03.89-3.81,2.14-5.37,3.75-1.55,1.61-2.77,3.49-3.64,5.65-.85,2.16-1.28,4.5-1.28,7.01ZM1032.4,22.92c0-3.01.52-5.8,1.56-8.38,1.04-2.57,2.49-4.82,4.34-6.73,1.86-1.93,4-3.43,6.42-4.49,2.44-1.08,5.06-1.62,7.84-1.62s5.39.54,7.81,1.62c2.44,1.06,4.58,2.56,6.42,4.49,1.86,1.91,3.31,4.16,4.35,6.73,1.06,2.57,1.59,5.37,1.59,8.38s-.53,5.8-1.59,8.38c-1.04,2.57-2.49,4.84-4.35,6.79-1.83,1.93-3.97,3.44-6.42,4.52-2.42,1.08-5.03,1.62-7.81,1.62s-5.39-.54-7.84-1.62c-2.42-1.08-4.56-2.58-6.42-4.52-1.85-1.95-3.3-4.21-4.34-6.79-1.04-2.57-1.56-5.37-1.56-8.38Z"
/>
</g>
</g>
</svg>
)
}
export function Smallest({ ...props }) {
return (
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 206.66 276.36"
{...props}
>
<g>
<path
className="fill-green-secondary"
d="M195.36,275.19l-88.08-39.68c-2.41-1.54-5.49-1.54-7.91,0l-88.08,39.68c-4.9,3.12-11.3-.39-11.3-6.19V7.34C0,3.29,3.29,0,7.34,0h191.97c4.05,0,7.34,3.29,7.34,7.34v261.65c0,5.8-6.41,9.32-11.3,6.19Z"
/>
<g>
<path
className="fill-green-primary"
d="M120.63,90.83H34.16v25.88h86.47v-25.88Z"
/>
<path
className="fill-green-primary"
d="M137.93,138.53H34.16v34.41h103.76v-34.41Z"
/>
<path
className="fill-green-primary"
d="M137.93,34.67H34.16v34.41h103.76v-34.41Z"
/>
<path
className="fill-green-primary"
d="M172.51,164.29c0-4.78-3.87-8.65-8.65-8.65s-8.65,3.87-8.65,8.65,3.87,8.65,8.65,8.65,8.65-3.87,8.65-8.65Z"
/>
</g>
</g>
</svg>
)
}

View File

@@ -1,88 +0,0 @@
import { createContext, useContext, useState } from 'react'
import {
Menu as HeadlessMenu,
MenuButton as HeadlessMenuButton,
MenuItem as HeadlessMenuItem,
MenuItems as HeadlessMenuItems,
} from '@headlessui/react'
import { Loader } from './loader'
import clsx from 'clsx'
const MenuContext = createContext(null)
export function useMenu() {
return useContext(MenuContext)
}
export function Menu({
children,
isLoading: defaultIsLoading = false,
...props
}) {
const [isLoading, setIsLoading] = useState(defaultIsLoading)
return (
<MenuContext.Provider
value={{ isLoading: isLoading || defaultIsLoading, setIsLoading }}
>
<HeadlessMenu {...props}>{children}</HeadlessMenu>
</MenuContext.Provider>
)
}
export function MenuButton({ children, className, disabled, ...props }) {
const { isLoading } = useContext(MenuContext)
return (
<HeadlessMenuButton
className={clsx(
className,
'relative overflow-hidden disabled:pointer-events-none',
)}
disabled={isLoading || disabled}
{...props}
>
{isLoading && (
<div className="absolute inset-0 flex justify-center items-center bg-white dark:bg-slate-800">
<Loader className="w-4" />
</div>
)}
{children}
</HeadlessMenuButton>
)
}
export function MenuItem({ children, className, ...props }) {
return (
<HeadlessMenuItem
className={clsx(
'relative flex items-center gap-1 py-2 px-4 hover:bg-zinc-100 dark:hover:bg-slate-600 w-full transition',
'aria-[disabled=true]:text-gray-400 aria-[disabled=true]:dark:text-gray-600',
'aria-[disabled=true]:pointer-events-none',
className,
)}
{...props}
>
{children}
</HeadlessMenuItem>
)
}
export function MenuItems({ children, className, ...props }) {
return (
<HeadlessMenuItems
className={clsx(
'absolute right-0 origin-top-right bg-white dark:bg-slate-700 rounded-lg drop-shadow shadow overflow-hidden py-2',
className,
)}
{...props}
>
{children}
</HeadlessMenuItems>
)
}
export function MenuSeparator() {
return <hr className="my-2 border-gray-200 dark:border-t-slate-600" />
}

View File

@@ -1,70 +0,0 @@
import {
useContext,
useMemo,
useCallback,
createContext,
useState,
useEffect,
} from 'react'
import * as Auth from 'aws-amplify/auth'
const AuthContext = createContext(null)
export function useAuth() {
const ctx = useContext(AuthContext)
if (!ctx) {
throw new Error('useAuth must be used within an AuthProvider')
}
return ctx
}
export function AuthProvider({ children }) {
const [authUser, setAuthUser] = useState(null)
useEffect(() => {
Auth.fetchUserAttributes()
.then((user) => {
setAuthUser(user)
})
.catch(() => {
setAuthUser(null)
})
}, [])
const signIn = useCallback(async ({ username, password }) => {
const signInOut = await Auth.signIn({
username,
password,
options: {
clientMetadata: {},
},
})
if (signInOut?.isSignedIn) {
setAuthUser(await Auth.fetchUserAttributes())
}
return signInOut
}, [])
const signOut = useCallback(async () => {
try {
return await Auth.signOut()
} catch {}
}, [])
const authContext = useMemo(
() => ({
authUser,
signIn,
signOut,
}),
[authUser, signIn, signOut],
)
return (
<AuthContext.Provider value={authContext}>{children}</AuthContext.Provider>
)
}

View File

@@ -1,57 +0,0 @@
import { useAuth } from '~/hooks/use-auth'
import { MenuButton, MenuItem as HeadlessMenuItem } from '@headlessui/react'
import {
ChevronDownIcon,
AdjustmentsHorizontalIcon,
ArrowRightStartOnRectangleIcon,
} from '@heroicons/react/24/solid'
import { BookOpenIcon } from '@heroicons/react/24/outline'
import { Menu, MenuItem, MenuItems, MenuSeparator } from '~/components/menu'
import clsx from 'clsx'
import { Link } from 'react-router'
export function UserMenu({ className }) {
const { authUser } = useAuth()
return (
<Menu as="div" className={clsx('relative', className)}>
<MenuButton className="flex gap-0.5 items-center cursor-pointer">
<div className="w-10 h-10 bg-zinc-200 dark:bg-gray-800 rounded-full overflow-hidden">
{/* <Avatar
name={authUser.name}
email={authUser.email}
size={40}
maxInitials={2}
/> */}
</div>
<ChevronDownIcon className="w-5 fill-gray-500 dark:fill-white" />
</MenuButton>
<MenuItems className="w-64 mt-1">
{/* User */}
<HeadlessMenuItem as="div" className="py-2 px-4">
<div className="font-semibold truncate">{authUser?.name}</div>
<div className="text-sm text-gray-600 dark:text-slate-300 truncate">
{authUser?.email}
</div>
</HeadlessMenuItem>
<MenuSeparator />
<MenuItem as={Link} target="_blank" to="/redirect-out">
<BookOpenIcon className="w-5" /> Sala de aula
</MenuItem>
<MenuSeparator />
<MenuItem as={Link} to="/settings">
<AdjustmentsHorizontalIcon className="w-5" /> Configurações
</MenuItem>
<MenuItem as={Link} to="/auth/logout">
<ArrowRightStartOnRectangleIcon className="w-5" /> Sair
</MenuItem>
</MenuItems>
</Menu>
)
}

View File

@@ -1,119 +0,0 @@
import { useNavigation, redirect, useNavigate } from 'react-router'
import { fetchAuthSession } from 'aws-amplify/auth'
import {
AcademicCapIcon,
PresentationChartLineIcon,
UserGroupIcon,
ShoppingBagIcon,
Bars3BottomLeftIcon,
} from '@heroicons/react/24/outline'
import { NavLink } from 'react-router'
import { Outlet } from 'react-router'
import { Container } from '~/components/container'
import { Smallest, Regular } from '~/components/logo'
import { clsx } from 'clsx'
import { UserMenu } from './_user-menu'
export async function clientLoader() {
const session = await fetchAuthSession()
if (!session?.tokens?.idToken) {
throw redirect('/auth')
}
}
export default function Layout() {
const navigation = useNavigation()
const isNavigating = Boolean(navigation.location)
return (
<div>
<aside
role="navigation"
className="p-4 w-80 h-full fixed top-0 left-0 bg-yellow-terciary dark:bg-green-primary z-40 overflow-y-auto max-lg:hidden"
>
<div className="space-y-6">
<Logo className="h-12 lg:h-14" />
<ul className="space-y-1 font-medium">
<Link to="/" icon={PresentationChartLineIcon}>
<>Visão geral</>
</Link>
<Link to="/orders" icon={ShoppingBagIcon}>
<>Pagamentos</>
</Link>
<Link to="/users" icon={UserGroupIcon}>
<>Usuários</>
</Link>
<Link to="/enrollments" icon={AcademicCapIcon}>
Matriculas
</Link>
</ul>
</div>
</aside>
<section className="lg:ml-80">
<header className="flex items-center bg-slate-50/50 dark:bg-gray-900/50 backdrop-blur backdrop-filter sticky top-0 border-b border-gray-200 dark:border-gray-700 lg:border-0 z-20 h-16 px-4 lg:px-8">
{/* Mobile menu button */}
<button className="lg:hidden" onClick={() => setIsOpen(true)}>
<span className="sr-only">Abrir barra lateral</span>
<Bars3BottomLeftIcon className="w-6" />
</button>
<div className="ml-auto flex items-center">
<UserMenu />
</div>
</header>
<main className="p-4 lg:p-8 space-y-5">
{isNavigating ? <Loading /> : <Outlet />}
</main>
</section>
</div>
)
}
function Link({ children, icon: Icon, ...props }) {
return (
<li>
<NavLink
className="aria-[current=page]:text-white aria-[current=page]:bg-green-dark hover:bg-green-secondary dark:hover:text-white p-2.5 rounded-lg flex gap-2 transition"
{...props}
>
<Icon className="w-6" />
<span>{children}</span>
</NavLink>
</li>
)
}
function Loading() {
return (
<Container>
<div className="animate-pulse flex flex-col gap-2.5 lg:w-2/4 [&>*]:bg-gray-200 dark:[&>*]:bg-gray-700 [&>*]:h-5 [&>*]:rounded">
<div className="w-2/6" />
<div className="w-4/6" />
<div className="w-5/6" />
<div className="w-5/6" />
<div className="w-6/6" />
<div className="w-6/6" />
<div className="w-3/6" />
<div className="w-5/6" />
<div className="w-4/6" />
<div className="w-4/6" />
</div>
</Container>
)
}
function Logo({ className }) {
return (
<div>
<Regular className={clsx(className)} />
{/* <Smallest className={clsx('lg:hidden w-full', className)} /> */}
</div>
)
}

View File

@@ -1,18 +0,0 @@
import { createElement } from 'react'
import clsx from 'clsx'
export function Link({ children, as = 'button', className, ...props }) {
return createElement(
as,
{
className: clsx(
className,
'text-green-primary dark:text-green-secondary underline hover:no-underline',
'disabled:no-underline disabled:cursor-not-allowed disabled:text-gray-400',
'dark:disabled:text-gray-600',
),
...props,
},
children,
)
}

View File

@@ -1,254 +0,0 @@
export default function Pulse({ ...props }) {
return (
<svg
{...props}
viewBox="0 0 973 1080"
fill="none"
xmlns="http://www.w3.org/2000/svg"
version="1.1"
>
<path
d="M473.832 562.531L449.083 551.386C448.408 550.953 447.542 550.953 446.859 551.386L422.11 562.531C420.733 563.405 418.933 562.419 418.933 560.792V487.309C418.941 486.167 419.868 485.241 421.01 485.241H474.949C476.092 485.241 477.018 486.167 477.018 487.309V560.792C477.018 562.419 475.217 563.405 473.841 562.531H473.832Z"
stroke="url(#paint0_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M492.032 593.277L449.863 574.287C448.713 573.55 447.238 573.55 446.073 574.287L403.904 593.277C401.559 594.766 398.491 593.086 398.491 590.314V465.11C398.506 463.164 400.084 461.586 402.031 461.586H493.935C495.882 461.586 497.46 463.164 497.46 465.11V590.314C497.46 593.086 494.392 594.766 492.047 593.277H492.032Z"
stroke="url(#paint1_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M511.592 628.14L450.701 600.719C449.04 599.654 446.91 599.654 445.228 600.719L384.337 628.14C380.951 630.29 376.521 627.863 376.521 623.86V443.069C376.542 440.259 378.821 437.981 381.632 437.981H514.34C517.151 437.981 519.43 440.259 519.43 443.069V623.86C519.43 627.863 515 630.29 511.613 628.14H511.592Z"
stroke="url(#paint2_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M536.741 684.081L451.779 645.82C449.461 644.335 446.489 644.335 444.142 645.82L359.18 684.081C354.455 687.082 348.274 683.695 348.274 678.11V418.448C348.303 414.527 351.483 411.348 355.406 411.348H447.99H540.574C544.497 411.348 547.677 414.527 547.677 418.448V678.11C547.677 683.695 541.496 687.082 536.771 684.081H536.741Z"
stroke="url(#paint3_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M564.722 729.385L452.978 679.063C449.93 677.109 446.021 677.109 442.933 679.063L331.19 729.385C324.975 733.331 316.845 728.877 316.845 721.532V389.752C316.885 384.595 321.067 380.414 326.226 380.414H569.764C574.923 380.414 579.105 384.595 579.105 389.752V721.532C579.105 728.877 570.976 733.331 564.761 729.385H564.722Z"
stroke="url(#paint4_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M593.093 771.607L454.194 709.057C450.404 706.629 445.546 706.629 441.708 709.057L302.809 771.607C295.085 776.512 284.979 770.976 284.979 761.846V349.44C285.028 343.03 290.226 337.834 296.639 337.834H599.36C605.773 337.834 610.971 343.03 610.971 349.44V761.846C610.971 770.976 600.866 776.512 593.141 771.607H593.093Z"
stroke="url(#paint5_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M623.352 824.278L455.491 748.685C450.911 745.75 445.04 745.75 440.401 748.685L272.54 824.278C263.204 830.206 250.992 823.515 250.992 812.481V314.082C251.051 306.335 257.333 300.055 265.083 300.055H630.926C638.676 300.055 644.959 306.335 644.959 314.082V812.481C644.959 823.515 632.746 830.206 623.411 824.278H623.352Z"
stroke="url(#paint6_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M654.35 873.823L456.819 784.868C451.43 781.415 444.521 781.415 439.063 784.868L241.532 873.823C230.546 880.798 216.175 872.925 216.175 859.941V273.45C216.245 264.333 223.637 256.944 232.757 256.944H663.262C672.382 256.944 679.775 264.333 679.775 273.45V859.941C679.775 872.925 665.404 880.798 654.419 873.823H654.35Z"
stroke="url(#paint7_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M682.916 921.114L458.043 819.846C451.908 815.915 444.043 815.915 437.829 819.846L212.956 921.114C200.45 929.055 184.09 920.092 184.09 905.31V237.637C184.168 227.259 192.584 218.846 202.967 218.846H693.063C703.445 218.846 711.861 227.259 711.861 237.637V905.31C711.861 920.092 695.501 929.055 682.995 921.114H682.916Z"
stroke="url(#paint8_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M713.306 972.068L459.345 857.702C452.417 853.262 443.534 853.262 436.517 857.702L182.556 972.068C168.432 981.036 149.956 970.914 149.956 954.221V200.184C150.045 188.463 159.55 178.962 171.275 178.962H724.765C736.49 178.962 745.995 188.463 745.995 200.184V954.221C745.995 970.914 727.518 981.036 713.395 972.068H713.306Z"
stroke="url(#paint9_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M748.558 1032.04L460.856 902.478C453.007 897.448 442.944 897.448 434.994 902.478L147.292 1032.04C131.292 1042.2 110.361 1030.73 110.361 1011.82V157.602C110.462 144.324 121.229 133.561 134.512 133.561H761.539C774.822 133.561 785.59 144.324 785.59 157.602V1011.82C785.59 1030.73 764.659 1042.2 748.658 1032.04H748.558Z"
stroke="url(#paint10_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M785.576 1097.37L462.442 951.851C453.626 946.202 442.324 946.202 433.395 951.851L110.261 1097.37C92.2904 1108.78 68.7815 1095.9 68.7815 1074.66V115.239C68.8945 100.325 80.9881 88.2367 95.9072 88.2367H800.156C815.076 88.2367 827.169 100.325 827.169 115.239V1074.66C827.169 1095.9 803.66 1108.78 785.689 1097.37H785.576Z"
stroke="url(#paint11_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M822.953 1145.33L464.044 986.709C454.252 980.552 441.698 980.552 431.781 986.709L72.872 1145.33C52.9117 1157.76 26.8001 1143.72 26.8001 1120.57V74.7882C26.9256 58.5325 40.358 45.3555 56.9289 45.3555H839.147C855.718 45.3555 869.151 58.5325 869.151 74.7882V1120.57C869.151 1143.72 843.039 1157.76 823.079 1145.33H822.953Z"
stroke="url(#paint12_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M864.495 1211.56L465.824 1036.52C454.948 1029.73 441.003 1029.73 429.987 1036.52L31.3159 1211.56C9.14429 1225.28 -19.8601 1209.79 -19.8601 1184.24V30.2317C-19.7207 12.2937 -4.80012 -2.24695 13.6065 -2.24695H882.484C900.89 -2.24695 915.811 12.2937 915.811 30.2317V1184.24C915.811 1209.79 886.806 1225.28 864.635 1211.56H864.495Z"
stroke="url(#paint13_radial_573_3412)"
strokeWidth="10"
/>
<path
d="M910.925 1278.92L467.814 1084.38C455.725 1076.83 440.226 1076.83 427.982 1084.38L-15.1291 1278.92C-39.7722 1294.18 -72.0098 1276.96 -72.0098 1248.56V-34.0846C-71.8548 -54.0221 -55.271 -70.1836 -34.8126 -70.1836H930.918C951.377 -70.1836 967.96 -54.0221 967.96 -34.0846V1248.56C967.96 1276.96 935.723 1294.18 911.08 1278.92H910.925Z"
stroke="url(#paint14_radial_573_3412)"
strokeWidth="10"
/>
<defs>
<radialGradient
id="paint0_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint1_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint2_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint3_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint4_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint5_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint6_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint7_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint8_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint9_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint10_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint11_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint12_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint13_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
<radialGradient
id="paint14_radial_573_3412"
cx="0"
cy="0"
r="1"
gradientUnits="userSpaceOnUse"
gradientTransform="translate(447.975 494.335) rotate(48.6533) scale(374.6 348.132)"
>
<stop stopColor="#8CD366" />
<stop offset="0.710979" stopColor="#FFCF82" stopOpacity="0.1" />
</radialGradient>
</defs>
</svg>
)
}

View File

@@ -1,76 +0,0 @@
import { Outlet, Link as RouterLink, useSearchParams } from 'react-router'
import { Regular as Logo } from '../../components/logo'
import Pulse from './_pulse'
import WomanImg from './woman.png'
import { Link } from './_link'
export default function Auth() {
const [searchParams] = useSearchParams()
const year = new Date().getFullYear()
return (
<>
<div className="min-h-screen xl:grid grid-cols-3 relative">
<div className="col-span-2 max-xl:hidden relative overflow-hidden">
<Pulse className="absolute -inset-y-1/4" />
<img
src={WomanImg}
alt="Educação que garente sua segurança"
className="absolute bottom-0 inset-x-1/2 h-4/6"
/>
<div className="absolute text-4xl top-12 left-12 font-bold">
Educação que
<br />
garante sua segurança
</div>
<div className="absolute left-12 bottom-12 text-gray-600 dark:text-gray-400 space-y-0.5">
<p>
&copy; {year} EDUSEG<sup>&reg;</sup>. Todos os direitos
reservados.
</p>
</div>
</div>
<div className="bg-yellow-terciary/70 dark:bg-gray-800/50 min-h-screen p-4 2xl:py-12 flex flex-col">
<div className="flex flex-col flex-1 justify-center items-center">
<Logo className="w-52 mb-8" />
<div className="space-y-2.5 xl:space-y-5">
<Outlet />
</div>
</div>
<div className="text-center mt-2.5 aria-hidden:hidden">
<Link
to={{
pathname: '/auth/support',
search: searchParams.toString(),
}}
as={RouterLink}
state={{ location: window.location.href }}
>
Precisa de ajuda? Fale conosco
</Link>
</div>
</div>
</div>
</>
)
}
export function Card({ children }) {
return (
<Container>
<div className="space-y-2.5 xl:space-y-5 rounded-xl bg-yellow-50 dark:bg-gray-700/60 p-4 lg:p-8 drop-shadow-xs shadow-xs">
{children}
</div>
</Container>
)
}
export function Container({ children }) {
return <div className="w-full 2xl:w-[26rem]">{children}</div>
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 932 KiB

View File

@@ -1,98 +0,0 @@
import {
isRouteErrorResponse,
Links,
Meta,
Outlet,
Scripts,
ScrollRestoration,
} from 'react-router'
import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
import { Amplify } from 'aws-amplify'
import { AuthProvider } from '~/hooks/use-auth'
import { Smallest as Logo } from '~/components/logo'
import amplifyconfig from './amplifyconfiguration.json'
import stylesheet from './app.css?url'
Amplify.configure(amplifyconfig)
export const links = () => [
{ rel: 'preconnect', href: 'https://fonts.googleapis.com' },
{
rel: 'preconnect',
href: 'https://fonts.gstatic.com',
crossOrigin: 'anonymous',
},
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100..900;1,100..900&display=swap',
},
{ rel: 'stylesheet', href: stylesheet },
]
export function Layout({ children }) {
return (
<html lang="en">
<head>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>EDUSEG&reg;</title>
<Meta />
<Links />
</head>
<body>
{children}
<ScrollRestoration />
<Scripts />
</body>
</html>
)
}
export default function App() {
const queryClient = new QueryClient()
return (
<QueryClientProvider client={queryClient}>
<AuthProvider>
<Outlet />
</AuthProvider>
</QueryClientProvider>
)
}
export function HydrateFallback() {
return (
<Logo className="w-14 absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 animate-pulse" />
)
}
export function ErrorBoundary({ error }) {
let message = 'Oops!'
let details = 'An unexpected error occurred.'
let stack
if (isRouteErrorResponse(error)) {
message = error.status === 404 ? '404' : 'Error'
details =
error.status === 404
? 'The requested page could not be found.'
: error.statusText || details
} else if (import.meta.env.DEV && error && error instanceof Error) {
details = error.message
stack = error.stack
}
return (
<main className="pt-16 p-4 container mx-auto">
<h1>{message}</h1>
<p>{details}</p>
{stack && (
<pre className="w-full p-4 overflow-x-auto">
<code>{stack}</code>
</pre>
)}
</main>
)
}

View File

@@ -1,24 +0,0 @@
import { index, route, layout, prefix } from '@react-router/dev/routes'
export default [
layout('layouts/app/layout.jsx', [
index('routes/overview/index.jsx'),
route('users', 'routes/users/index.jsx'),
route('users/:id', 'routes/users/$id.jsx'),
route('orders', 'routes/orders/index.jsx'),
route('orders/:id', 'routes/orders/$id.jsx'),
route('enrollments', 'routes/enrollments/index.jsx'),
route('enrollments/:id', 'routes/enrollments/$id.jsx'),
route('settings', 'routes/settings/index.jsx'),
]),
layout('layouts/auth/layout.jsx', [
...prefix('auth', [
index('routes/auth/login/index.jsx'),
route('logout', 'routes/auth/logout.jsx'),
route('register', 'routes/auth/register/index.jsx'),
route('forgot', 'routes/auth/forgot/index.jsx'),
route('passcode', 'routes/auth/passcode/index.jsx'),
route('support', 'routes/auth/support.jsx'),
]),
]),
]

View File

@@ -1,13 +0,0 @@
import { encodeURI, decode } from 'js-base64'
export function encode(data) {
return encodeURI(JSON.stringify(data))
}
export function parse(str) {
try {
return JSON.parse(decode(str))
} catch {
return null
}
}

View File

@@ -1,9 +0,0 @@
export default function Forgot() {
return (
<form>
<h1>Verifique sua caixa de email para continuar</h1>
Username
<input />
</form>
)
}

View File

@@ -1,173 +0,0 @@
import {
Button,
Control,
Input,
Checkbox,
Label,
Error,
} from '~/components/form'
import { useForm } from 'react-hook-form'
import { ErrorMessage } from '@hookform/error-message'
import { yupResolver } from '@hookform/resolvers/yup'
import { Link as RouterLink, useNavigate, useSearchParams } from 'react-router'
import { useAuth } from '~/hooks/use-auth'
import { useToggle } from '@uidotdev/usehooks'
import { Heading } from '~/components/heading'
import { Link } from '~/layouts/auth/_link'
import { Card } from '~/layouts/auth/layout'
import * as yup from 'yup'
import { parse } from '../_base64state'
const schema = yup.object({
password: yup
.string()
.trim()
.min(6, 'A senha deve ter pelo menos 6 caracteres')
.required('Você deve digitar uma senha'),
})
export default function Password() {
const navigate = useNavigate()
const [searchParams] = useSearchParams()
const [on, toggle] = useToggle()
const { signIn } = useAuth()
const { register, formState, setError, handleSubmit } = useForm({
resolver: yupResolver(schema),
})
const state = parse(searchParams.get('state'))
const formError = (message) => {
setError('password', {
type: 'manual',
message,
})
}
const onSubmit = async ({ password }) => {
const username = state?.email
const redirectTo = searchParams.get('redirect') ?? '/'
try {
const { nextStep } = await signIn({ username, password })
if (nextStep.signInStep === 'CONFIRM_SIGN_UP') {
return navigate({
pathname: '../signup/confirm',
search: searchParams.toString(),
})
}
// User is required to set a new password after temporary password login
if (
nextStep.signInStep === 'CONFIRM_SIGN_IN_WITH_NEW_PASSWORD_REQUIRED'
) {
return navigate({
pathname: '../reset',
search: searchParams.toString(),
})
}
// User needs to reset their password due to a forgot password request
if (nextStep.signInStep === 'RESET_PASSWORD') {
return navigate({
pathname: '../forgot',
search: searchParams.toString(),
})
}
return navigate(redirectTo)
} catch (err) {
const { message } = err
switch (message) {
case 'Incorrect username or password.':
return formError(
'A senha está incorreta, tente novamente. Tente redefinir a senha clicando em "Esqueceu sua senha".',
)
case 'Password attempts exceeded':
return formError(
'Tentativas excedidas. Espere alguns minutos para tentar novamente.',
)
case 'Temporary password has expired and must be reset by an administrator.':
return formError(
'A senha temporária expirou. Entre em contato conosco para pedir uma nova.',
)
case 'User does not exist.':
return navigate({
pathname: '../signup',
search: searchParams.toString(),
})
case 'There is already a signed in user.':
// If the user is already signed in, redirect them.
return navigate(redirectTo)
default:
return formError(message)
}
}
}
return (
<>
<Card>
<div className="space-y-1.5">
<Heading as="h2" size="lg">
Digite sua senha
</Heading>
<p className="break-all">
Entre na sua conta usando o email{' '}
<span className="font-semibold">{state?.email}</span>{' '}
<Link to="." as={RouterLink}>
(editar)
</Link>
</p>
</div>
<form onSubmit={handleSubmit(onSubmit)} className="space-y-2.5">
<div className="space-y-1">
<Control
className="space-y-0.5"
aria-invalid={'password' in formState.errors}
>
<Label aria-required={true}>Senha</Label>
<Input
type={on ? 'text' : 'password'}
className="w-full"
autoComplete="off"
autoFocus={true}
{...register('password')}
/>
<ErrorMessage
errors={formState.errors}
name="password"
render={({ message }) => <Error>{message}</Error>}
/>
</Control>
<Control className="flex items-center gap-1.5">
<Checkbox onChange={toggle} />
<Label>Mostrar senha</Label>
</Control>
</div>
<Button
type="submit"
className="w-full"
isLoading={formState.isSubmitting}
>
Entrar
</Button>
</form>
</Card>
<div className="text-center">
<Link
to={{ pathname: '../forgot', search: searchParams.toString() }}
as={RouterLink}
>
Esqueceu sua senha?
</Link>
</div>
</>
)
}

View File

@@ -1,136 +0,0 @@
import { useSearchParams, Link } from 'react-router'
import { useForm } from 'react-hook-form'
import { ErrorMessage } from '@hookform/error-message'
import { isValidCPF } from '@brazilian-utils/brazilian-utils'
import { yupResolver } from '@hookform/resolvers/yup'
import { Card } from '~/layouts/auth/layout'
import { Control, Label, Input, Button, Error } from '~/components/form'
import { Heading } from '~/components/heading'
import { useMutation } from '@tanstack/react-query'
import * as yup from 'yup'
import { encode, parse } from '../_base64state'
import axios from '~/axios'
import Password from './_password'
yup.addMethod(yup.string, 'username', function (message) {
return this.test(
'username',
message,
(x) => isValidCPF(x) || yup.string().email().isValid(x),
)
})
export const schema = yup.object({
username: yup
.string()
.trim()
.lowercase()
.username('Deve ser um Email ou CPF válido')
.transform((x) => (isValidCPF(x) ? x.replace(/\D/g, '') : x))
.required('Digite um Email ou CPF'),
})
export default function Component() {
const [searchParams] = useSearchParams()
const state = parse(searchParams.get('state'))
if (state?.['cognito:sub']) {
return <Password />
}
return <SignIn />
}
function SignIn() {
const [searchParams, setSearchParams] = useSearchParams()
const { handleSubmit, formState, setError, register } = useForm({
resolver: yupResolver(schema),
})
const { mutateAsync } = useMutation({
mutationFn: async ({ username }) => {
const { data } = await axios.get(`/search/lookup/${username}`)
return data
},
onSuccess: (data) => {
setSearchParams((searchParams) => {
searchParams.set('state', encode(data))
return searchParams
})
},
})
const formError = (message) => {
setError('username', {
type: 'manual',
message,
})
}
const onSubmit = async ({ username }) => {
try {
await mutateAsync({ username })
} catch ({ message }) {
switch (message) {
case 'User not found.':
return formError(
'Não encontramos sua conta. Por favor, verifique se seu Email ou CPF estão corretos.',
)
default:
return formError(message)
}
}
}
return (
<Card>
<Heading>Digite o seu email ou cpf para continuar</Heading>
{/* Sign in */}
<form onSubmit={handleSubmit(onSubmit)} className="space-y-2.5">
<Control
className="space-y-0.5"
aria-invalid={'username' in formState.errors}
>
<Label aria-required={true}>Email ou CPF</Label>
<Input
className="w-full"
autoFocus={true}
{...register('username')}
/>
<ErrorMessage
errors={formState.errors}
name="username"
render={({ message }) => <Error>{message}</Error>}
/>
</Control>
<Button
type="submit"
className="w-full"
isLoading={formState.isSubmitting}
>
Continuar
</Button>
</form>
<div className="flex justify-center items-center gap-4">
<span className="flex-1 h-px bg-yellow-secondary dark:bg-gray-700" />
<span>ou</span>
<span className="flex-1 h-px bg-yellow-secondary dark:bg-gray-700" />
</div>
<Button
as={Link}
to={{
pathname: './passcode',
search: searchParams.toString(),
}}
relative="path"
className="flex justify-center items-center !bg-yellow-primary w-full"
>
Entrar com código de acesso
</Button>
</Card>
)
}

View File

@@ -1,15 +0,0 @@
import { useNavigate } from 'react-router'
import { useEffect } from 'react'
import { useAuth } from '~/hooks/use-auth'
export default function Component() {
const { signOut } = useAuth()
const navigate = useNavigate()
useEffect(() => {
signOut()
navigate('/auth')
}, [])
return <></>
}

View File

@@ -1,3 +0,0 @@
export default function Component() {
return <>passcode index</>
}

View File

@@ -1,8 +0,0 @@
export default function Signup() {
return (
<form>
Username
<input />
</form>
)
}

View File

@@ -1,9 +0,0 @@
import { Heading } from '~/components/heading'
export default function Component() {
return (
<>
<Heading>...</Heading>
</>
)
}

View File

@@ -1,7 +0,0 @@
import { useParams } from 'react-router'
export default function Component() {
const { id } = useParams()
return <>enrollments single {id}</>
}

View File

@@ -1,7 +0,0 @@
export function meta({}) {
return [{ title: 'Matrículas' }]
}
export default function Component() {
return <>enrollments index</>
}

View File

@@ -1,12 +0,0 @@
import { Welcome } from "../welcome/welcome";
export function meta() {
return [
{ title: "New React Router App" },
{ name: "description", content: "Welcome to React Router!" },
];
}
export default function Home() {
return <Welcome />;
}

View File

@@ -1,7 +0,0 @@
import { useParams } from 'react-router'
export default function Component() {
const { id } = useParams()
return <>order single {id}</>
}

View File

@@ -1,7 +0,0 @@
export function meta({}) {
return [{ title: 'Pagamentos' }]
}
export default function Component() {
return <>overview single</>
}

View File

@@ -1,7 +0,0 @@
export function meta({}) {
return [{ title: 'Visão geral' }]
}
export default function Component() {
return <>overview index</>
}

View File

@@ -1,3 +0,0 @@
export default function Component() {
return <>settings index</>
}

View File

@@ -1,7 +0,0 @@
import { useParams } from 'react-router'
export default function Component() {
const { id } = useParams()
return <>user single {id}</>
}

View File

@@ -1,74 +0,0 @@
import { memo } from 'react'
import { Heading } from '~/components/heading'
import { CpfCnpj } from '~/components/cpf-cnpj'
import { Table, Tbody, Td, Th, Thead, Tr } from '~/components/table'
import { Abbr } from '~/components/abbr'
import { Datetime } from '~/components/datetime'
import axios from '~/axios'
export function meta({}) {
return [{ title: 'Usuários' }]
}
export async function clientLoader() {
await new Promise((r) => setTimeout(r, 2000))
const index = 'users'
const { data } = await axios.get('/search/', { params: { index } })
return data
}
export default function Component({ loaderData: { hits = [] } }) {
return (
<>
<Heading>Usuários</Heading>
<Table>
<Thead>
<Tr>
<Th>&nbsp;</Th>
<Th>Nome</Th>
<Th>CPF/CNPJ</Th>
<Th>Email</Th>
<Th>Último acesso</Th>
</Tr>
</Thead>
<Tbody>
{hits.map((props) => (
<Row key={props.id} {...props} />
))}
{hits.length === 0 && (
<Tr className="no-hover">
<Td colSpan={5}>Nada encontrado</Td>
</Tr>
)}
</Tbody>
</Table>
</>
)
}
const Row = memo(function Row({
id,
name,
cpf,
cnpj,
email,
lastLogin: last_login,
}) {
return (
<Tr className="cursor-pointer" data-hover={!cnpj}>
<Td>
<Abbr maxLen={6}>{id}</Abbr>
</Td>
<Td>
<Abbr>{name}</Abbr>
</Td>
<CpfCnpj as={Td}>{cpf ?? cnpj}</CpfCnpj>
<Td>
<Abbr>{email}</Abbr>
</Td>
<Datetime as={Td}>{last_login}</Datetime>
</Tr>
)
})

View File

@@ -1,23 +0,0 @@
<svg width="1080" height="174" viewBox="0 0 1080 174" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M231.527 86.9999C231.527 94.9642 228.297 102.173 223.067 107.387C217.837 112.606 210.614 115.835 202.634 115.835C194.654 115.835 187.43 119.059 182.206 124.278C176.977 129.498 173.741 136.707 173.741 144.671C173.741 152.635 170.51 159.844 165.281 165.058C160.051 170.277 152.828 173.507 144.847 173.507C136.867 173.507 129.644 170.277 124.42 165.058C119.19 159.844 115.954 152.635 115.954 144.671C115.954 136.707 119.19 129.498 124.42 124.278C129.644 119.059 136.867 115.835 144.847 115.835C152.828 115.835 160.051 112.606 165.281 107.387C170.51 102.173 173.741 94.9642 173.741 86.9999C173.741 71.0711 160.808 58.1643 144.847 58.1643C136.867 58.1643 129.644 54.9347 124.42 49.7155C119.19 44.502 115.954 37.2931 115.954 29.3287C115.954 21.3643 119.19 14.1555 124.42 8.93622C129.644 3.71698 136.867 0.493164 144.847 0.493164C160.808 0.493164 173.741 13.4 173.741 29.3287C173.741 37.2931 176.977 44.502 182.206 49.7155C187.43 54.9347 194.654 58.1643 202.634 58.1643C218.594 58.1643 231.527 71.0711 231.527 86.9999Z" fill="#F44250"/>
<path d="M115.954 86.9996C115.954 71.0742 103.018 58.1641 87.061 58.1641C71.1037 58.1641 58.1677 71.0742 58.1677 86.9996C58.1677 102.925 71.1037 115.835 87.061 115.835C103.018 115.835 115.954 102.925 115.954 86.9996Z" fill="white"/>
<path d="M58.1676 144.671C58.1676 128.745 45.2316 115.835 29.2743 115.835C13.317 115.835 0.381104 128.745 0.381104 144.671C0.381104 160.596 13.317 173.506 29.2743 173.506C45.2316 173.506 58.1676 160.596 58.1676 144.671Z" fill="white"/>
<path d="M289.314 144.671C289.314 128.745 276.378 115.835 260.42 115.835C244.463 115.835 231.527 128.745 231.527 144.671C231.527 160.596 244.463 173.506 260.42 173.506C276.378 173.506 289.314 160.596 289.314 144.671Z" fill="white"/>
<g clip-path="url(#clip0_202_2131)">
<path d="M562.482 173.247C524.388 173.247 498.363 147.49 498.363 110.468C498.363 73.4455 524.388 47.6885 562.482 47.6885C600.576 47.6885 626.869 73.7135 626.869 110.468C626.869 147.222 600.576 173.247 562.482 173.247ZM562.482 144.007C579.385 144.007 587.703 130.319 587.703 110.468C587.703 90.6168 579.385 76.9289 562.482 76.9289C545.579 76.9289 537.529 90.6168 537.529 110.468C537.529 130.319 545.311 144.007 562.482 144.007Z" fill="white"/>
<path d="M833.64 141.116C824.217 141.116 819.237 136.684 819.237 126.156V74.8983H851.928V47.7792H819.237V1.15527H791.75L786.1 26.1978C783.343 36.4805 780.82 42.822 773.897 46.0821C773.105 46.4506 771.129 46.9976 769.409 47.3884C768.014 47.701 766.596 47.8573 765.167 47.8573H752.338V47.9243H734.832C723.578 47.9243 714.445 57.0459 714.445 68.3111V111.552C714.445 130.599 707.199 142.668 692.719 142.668C678.238 142.668 672.868 133.279 672.868 116.375V47.9243H634.249V125.765C634.249 151.254 644.442 173.248 676.63 173.248C691.915 173.248 703.895 167.231 711.096 157.182C712.145 155.72 714.445 156.49 714.445 158.276V170.022H753.332V83.8412C753.332 78.8953 757.34 74.8871 762.286 74.8871H779.882V136.952C779.882 164.663 797.89 173.248 817.842 173.248C833.908 173.248 844.436 169.374 853.58 162.441V136.126C846.1 139.453 839.725 141.116 833.629 141.116H833.64Z" fill="white"/>
<path d="M981.561 130.865C975.387 157.962 954.197 173.258 923.07 173.258C885.243 173.258 858.415 150.18 858.415 112.354C858.415 74.5281 885.779 47.6992 922.266 47.6992C961.699 47.6992 982.365 74.796 982.365 107.263V113.884H896.509C894.555 135.711 909.382 144.017 924.409 144.017C937.829 144.017 946.136 138.915 950.434 127.918L981.561 130.865ZM945.075 94.9372C944.271 83.1361 936.757 75.8567 921.998 75.8567C906.434 75.8567 899.188 82.321 897.045 94.9372H945.064H945.075Z" fill="white"/>
<path d="M1076.24 85.7486C1070.06 82.2652 1064.17 80.9142 1055.85 80.9142C1039.75 80.9142 1029.02 90.0358 1029.02 110.691V170.02H990.393V47.9225H1029.02V64.3235C1029.02 65.4623 1030.54 65.8195 1031.05 64.8035C1036.68 53.5718 1047.91 44.707 1062.03 44.707C1069.27 44.707 1075.45 46.8507 1078.66 49.5414L1076.25 85.7597L1076.24 85.7486Z" fill="white"/>
<path d="M547.32 31.5345V23.9983H522.457V31.5345H515.378V2.23828H542.14C553.562 2.23828 554.365 2.95282 554.365 13.1239C554.365 17.4111 553.472 18.5611 551.329 19.6553L549.408 20.6378L551.317 21.6426C553.595 22.8372 554.365 23.2391 554.365 30.0273V31.5345H547.332H547.32ZM522.457 18.3601H547.32V7.88763H522.457V18.349V18.3601Z" fill="white"/>
<path d="M578.493 2.23828H610.826V7.90996H580.067V14.5083H610.011V19.2868H580.067V25.8963H610.837V31.501L578.504 31.5345C575.344 31.5345 572.787 28.9778 572.787 25.8293V7.95462C572.787 4.80617 575.344 2.24945 578.493 2.24945V2.23828Z" fill="white"/>
<path d="M655.562 31.5345L653.151 26.3429H633.746L631.335 31.5345H624.58L637.006 4.75034C637.71 3.22078 639.262 2.23828 640.936 2.23828H645.927C647.613 2.23828 649.154 3.22078 649.857 4.75034L662.283 31.5345H655.529H655.562ZM643.46 8.06627C642.712 8.06627 642.053 8.49053 641.729 9.17158L635.968 21.5756H650.94L645.19 9.17158C644.878 8.49053 644.208 8.06627 643.46 8.06627Z" fill="white"/>
<path d="M694.862 32.4153C676.05 32.4153 675.313 32.4153 675.313 16.8852C675.313 1.35505 676.05 1.36621 694.862 1.36621C711.721 1.36621 713.764 2.06959 714.244 10.5325H707.333V7.01556H682.168V26.766H707.333V23.2714H714.244C713.775 31.7119 711.721 32.4153 694.862 32.4153Z" fill="white"/>
<path d="M745.282 31.5345V7.02795H729.16V2.23828H768.147V7.02795H752.025V31.5345H745.282Z" fill="white"/>
<path d="M454.419 169.819C450.935 165.264 448.792 154.814 447.452 137.397C446.112 118.104 437.806 113.817 422.532 113.817H392.254V169.83H347.494V0.986328H432.715C476.391 0.986328 498.106 21.6187 498.106 54.5882C498.106 79.2399 482.833 95.3171 462.201 98.0078C479.618 101.491 489.8 111.405 491.675 130.966C494.087 156.154 494.891 163.656 500.518 169.819H454.419ZM424.676 78.704C443.969 78.704 453.615 73.8808 453.615 58.3395C453.615 44.6739 443.969 37.4392 424.676 37.4392H392.254V78.7152H424.676V78.704Z" fill="white"/>
</g>
<defs>
<clipPath id="clip0_202_2131">
<rect width="731.156" height="172.261" fill="white" transform="translate(347.494 0.986328)"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -1,23 +0,0 @@
<svg width="1080" height="174" viewBox="0 0 1080 174" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M231.527 86.9999C231.527 94.9642 228.297 102.173 223.067 107.387C217.837 112.606 210.614 115.835 202.634 115.835C194.654 115.835 187.43 119.059 182.206 124.278C176.977 129.498 173.741 136.707 173.741 144.671C173.741 152.635 170.51 159.844 165.281 165.058C160.051 170.277 152.828 173.507 144.847 173.507C136.867 173.507 129.644 170.277 124.42 165.058C119.19 159.844 115.954 152.635 115.954 144.671C115.954 136.707 119.19 129.498 124.42 124.278C129.644 119.059 136.867 115.835 144.847 115.835C152.828 115.835 160.051 112.606 165.281 107.387C170.51 102.173 173.741 94.9642 173.741 86.9999C173.741 71.0711 160.808 58.1643 144.847 58.1643C136.867 58.1643 129.644 54.9347 124.42 49.7155C119.19 44.502 115.954 37.2931 115.954 29.3287C115.954 21.3643 119.19 14.1555 124.42 8.93622C129.644 3.71698 136.867 0.493164 144.847 0.493164C160.808 0.493164 173.741 13.4 173.741 29.3287C173.741 37.2931 176.977 44.502 182.206 49.7155C187.43 54.9347 194.654 58.1643 202.634 58.1643C218.594 58.1643 231.527 71.0711 231.527 86.9999Z" fill="#F44250"/>
<path d="M115.954 86.9996C115.954 71.0742 103.018 58.1641 87.0608 58.1641C71.1035 58.1641 58.1676 71.0742 58.1676 86.9996C58.1676 102.925 71.1035 115.835 87.0608 115.835C103.018 115.835 115.954 102.925 115.954 86.9996Z" fill="#121212"/>
<path d="M58.1676 144.671C58.1676 128.745 45.2316 115.835 29.2743 115.835C13.317 115.835 0.381104 128.745 0.381104 144.671C0.381104 160.596 13.317 173.506 29.2743 173.506C45.2316 173.506 58.1676 160.596 58.1676 144.671Z" fill="#121212"/>
<path d="M289.313 144.671C289.313 128.745 276.378 115.835 260.42 115.835C244.463 115.835 231.527 128.745 231.527 144.671C231.527 160.596 244.463 173.506 260.42 173.506C276.378 173.506 289.313 160.596 289.313 144.671Z" fill="#121212"/>
<g clip-path="url(#clip0_171_1761)">
<path d="M562.482 173.247C524.388 173.247 498.363 147.49 498.363 110.468C498.363 73.4455 524.388 47.6885 562.482 47.6885C600.576 47.6885 626.869 73.7135 626.869 110.468C626.869 147.222 600.576 173.247 562.482 173.247ZM562.482 144.007C579.386 144.007 587.703 130.319 587.703 110.468C587.703 90.6168 579.386 76.9289 562.482 76.9289C545.579 76.9289 537.529 90.6168 537.529 110.468C537.529 130.319 545.311 144.007 562.482 144.007Z" fill="#121212"/>
<path d="M833.64 141.116C824.217 141.116 819.237 136.684 819.237 126.156V74.8983H851.928V47.7792H819.237V1.15527H791.75L786.1 26.1978C783.343 36.4805 780.82 42.822 773.897 46.0821C773.105 46.4506 771.129 46.9976 769.409 47.3884C768.014 47.701 766.596 47.8573 765.167 47.8573H752.338V47.9243H734.832C723.578 47.9243 714.445 57.0459 714.445 68.3111V111.552C714.445 130.599 707.199 142.668 692.719 142.668C678.238 142.668 672.868 133.279 672.868 116.375V47.9243H634.249V125.765C634.249 151.254 644.442 173.248 676.63 173.248C691.915 173.248 703.895 167.231 711.096 157.182C712.145 155.72 714.445 156.49 714.445 158.276V170.022H753.332V83.8412C753.332 78.8953 757.34 74.8871 762.286 74.8871H779.882V136.952C779.882 164.663 797.89 173.248 817.842 173.248C833.908 173.248 844.436 169.374 853.58 162.441V136.126C846.1 139.453 839.725 141.116 833.629 141.116H833.64Z" fill="#121212"/>
<path d="M981.561 130.865C975.387 157.962 954.197 173.258 923.07 173.258C885.243 173.258 858.415 150.18 858.415 112.354C858.415 74.5281 885.779 47.6992 922.266 47.6992C961.699 47.6992 982.365 74.796 982.365 107.263V113.884H896.509C894.555 135.711 909.382 144.017 924.409 144.017C937.829 144.017 946.136 138.915 950.434 127.918L981.561 130.865ZM945.075 94.9372C944.271 83.1361 936.757 75.8567 921.998 75.8567C906.434 75.8567 899.188 82.321 897.045 94.9372H945.064H945.075Z" fill="#121212"/>
<path d="M1076.24 85.7486C1070.06 82.2652 1064.17 80.9142 1055.85 80.9142C1039.75 80.9142 1029.02 90.0358 1029.02 110.691V170.02H990.393V47.9225H1029.02V64.3235C1029.02 65.4623 1030.54 65.8195 1031.05 64.8035C1036.68 53.5718 1047.91 44.707 1062.03 44.707C1069.27 44.707 1075.45 46.8507 1078.66 49.5414L1076.25 85.7597L1076.24 85.7486Z" fill="#121212"/>
<path d="M547.321 31.5345V23.9983H522.457V31.5345H515.378V2.23828H542.14C553.562 2.23828 554.366 2.95282 554.366 13.1239C554.366 17.4111 553.472 18.5611 551.329 19.6553L549.408 20.6378L551.318 21.6426C553.595 22.8372 554.366 23.2391 554.366 30.0273V31.5345H547.332H547.321ZM522.457 18.3601H547.321V7.88763H522.457V18.349V18.3601Z" fill="#121212"/>
<path d="M578.493 2.23828H610.826V7.90996H580.067V14.5083H610.011V19.2868H580.067V25.8963H610.837V31.501L578.504 31.5345C575.344 31.5345 572.787 28.9778 572.787 25.8293V7.95462C572.787 4.80617 575.344 2.24945 578.493 2.24945V2.23828Z" fill="#121212"/>
<path d="M655.562 31.5345L653.151 26.3429H633.747L631.335 31.5345H624.58L637.007 4.75034C637.71 3.22078 639.262 2.23828 640.937 2.23828H645.927C647.613 2.23828 649.154 3.22078 649.857 4.75034L662.284 31.5345H655.529H655.562ZM643.46 8.06627C642.712 8.06627 642.053 8.49053 641.729 9.17158L635.968 21.5756H650.94L645.19 9.17158C644.878 8.49053 644.208 8.06627 643.46 8.06627Z" fill="#121212"/>
<path d="M694.862 32.4153C676.05 32.4153 675.313 32.4153 675.313 16.8852C675.313 1.35505 676.05 1.36621 694.862 1.36621C711.721 1.36621 713.764 2.06959 714.244 10.5325H707.333V7.01556H682.168V26.766H707.333V23.2714H714.244C713.775 31.7119 711.721 32.4153 694.862 32.4153Z" fill="#121212"/>
<path d="M745.282 31.5345V7.02795H729.16V2.23828H768.148V7.02795H752.026V31.5345H745.282Z" fill="#121212"/>
<path d="M454.419 169.819C450.935 165.264 448.792 154.814 447.452 137.397C446.112 118.104 437.806 113.817 422.532 113.817H392.254V169.83H347.494V0.986328H432.715C476.391 0.986328 498.106 21.6187 498.106 54.5882C498.106 79.2399 482.833 95.3171 462.201 98.0078C479.618 101.491 489.8 111.405 491.676 130.966C494.087 156.154 494.891 163.656 500.518 169.819H454.419ZM424.676 78.704C443.969 78.704 453.615 73.8808 453.615 58.3395C453.615 44.6739 443.969 37.4392 424.676 37.4392H392.254V78.7152H424.676V78.704Z" fill="#121212"/>
</g>
<defs>
<clipPath id="clip0_171_1761">
<rect width="731.156" height="172.261" fill="white" transform="translate(347.494 0.986328)"/>
</clipPath>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 6.0 KiB

View File

@@ -1,89 +0,0 @@
import logoDark from "./logo-dark.svg";
import logoLight from "./logo-light.svg";
export function Welcome() {
return (
<main className="flex items-center justify-center pt-16 pb-4">
<div className="flex-1 flex flex-col items-center gap-16 min-h-0">
<header className="flex flex-col items-center gap-9">
<div className="w-[500px] max-w-[100vw] p-4">
<img
src={logoLight}
alt="React Router"
className="block w-full dark:hidden"
/>
<img
src={logoDark}
alt="React Router"
className="hidden w-full dark:block"
/>
</div>
</header>
<div className="max-w-[300px] w-full space-y-6 px-4">
<nav className="rounded-3xl border border-gray-200 p-6 dark:border-gray-700 space-y-4">
<p className="leading-6 text-gray-700 dark:text-gray-200 text-center">
What&apos;s next?
</p>
<ul>
{resources.map(({ href, text, icon }) => (
<li key={href}>
<a
className="group flex items-center gap-3 self-stretch p-3 leading-normal text-blue-700 hover:underline dark:text-blue-500"
href={href}
target="_blank"
rel="noreferrer"
>
{icon}
{text}
</a>
</li>
))}
</ul>
</nav>
</div>
</div>
</main>
);
}
const resources = [
{
href: "https://reactrouter.com/docs",
text: "React Router Docs",
icon: (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="20"
viewBox="0 0 20 20"
fill="none"
className="stroke-gray-600 group-hover:stroke-current dark:stroke-gray-300"
>
<path
d="M9.99981 10.0751V9.99992M17.4688 17.4688C15.889 19.0485 11.2645 16.9853 7.13958 12.8604C3.01467 8.73546 0.951405 4.11091 2.53116 2.53116C4.11091 0.951405 8.73546 3.01467 12.8604 7.13958C16.9853 11.2645 19.0485 15.889 17.4688 17.4688ZM2.53132 17.4688C0.951566 15.8891 3.01483 11.2645 7.13974 7.13963C11.2647 3.01471 15.8892 0.951453 17.469 2.53121C19.0487 4.11096 16.9854 8.73551 12.8605 12.8604C8.73562 16.9853 4.11107 19.0486 2.53132 17.4688Z"
strokeWidth="1.5"
strokeLinecap="round"
/>
</svg>
),
},
{
href: "https://rmx.as/discord",
text: "Join Discord",
icon: (
<svg
xmlns="http://www.w3.org/2000/svg"
width="24"
height="20"
viewBox="0 0 24 20"
fill="none"
className="stroke-gray-600 group-hover:stroke-current dark:stroke-gray-300"
>
<path
d="M15.0686 1.25995L14.5477 1.17423L14.2913 1.63578C14.1754 1.84439 14.0545 2.08275 13.9422 2.31963C12.6461 2.16488 11.3406 2.16505 10.0445 2.32014C9.92822 2.08178 9.80478 1.84975 9.67412 1.62413L9.41449 1.17584L8.90333 1.25995C7.33547 1.51794 5.80717 1.99419 4.37748 2.66939L4.19 2.75793L4.07461 2.93019C1.23864 7.16437 0.46302 11.3053 0.838165 15.3924L0.868838 15.7266L1.13844 15.9264C2.81818 17.1714 4.68053 18.1233 6.68582 18.719L7.18892 18.8684L7.50166 18.4469C7.96179 17.8268 8.36504 17.1824 8.709 16.4944L8.71099 16.4904C10.8645 17.0471 13.128 17.0485 15.2821 16.4947C15.6261 17.1826 16.0293 17.8269 16.4892 18.4469L16.805 18.8725L17.3116 18.717C19.3056 18.105 21.1876 17.1751 22.8559 15.9238L23.1224 15.724L23.1528 15.3923C23.5873 10.6524 22.3579 6.53306 19.8947 2.90714L19.7759 2.73227L19.5833 2.64518C18.1437 1.99439 16.6386 1.51826 15.0686 1.25995ZM16.6074 10.7755L16.6074 10.7756C16.5934 11.6409 16.0212 12.1444 15.4783 12.1444C14.9297 12.1444 14.3493 11.6173 14.3493 10.7877C14.3493 9.94885 14.9378 9.41192 15.4783 9.41192C16.0471 9.41192 16.6209 9.93851 16.6074 10.7755ZM8.49373 12.1444C7.94513 12.1444 7.36471 11.6173 7.36471 10.7877C7.36471 9.94885 7.95323 9.41192 8.49373 9.41192C9.06038 9.41192 9.63892 9.93712 9.6417 10.7815C9.62517 11.6239 9.05462 12.1444 8.49373 12.1444Z"
strokeWidth="1.5"
/>
</svg>
),
},
];

View File

@@ -1,7 +0,0 @@
{
"compilerOptions": {
"paths": {
"~/*": ["./app/*"]
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +0,0 @@
{
"name": "dashboard_js",
"private": true,
"type": "module",
"scripts": {
"build": "react-router build",
"dev": "react-router dev",
"start": "react-router-serve ./build/server/index.js"
},
"dependencies": {
"@brazilian-utils/brazilian-utils": "^1.0.0-rc.12",
"@headlessui/react": "^2.2.0",
"@heroicons/react": "^2.2.0",
"@hookform/error-message": "^2.0.1",
"@hookform/resolvers": "^4.1.0",
"@react-router/node": "^7.2.0",
"@react-router/serve": "^7.2.0",
"@tanstack/react-query": "^5.66.9",
"@uidotdev/usehooks": "^2.4.1",
"aws-amplify": "^6.13.1",
"axios": "^1.7.9",
"bodybuilder": "^2.5.1",
"clsx": "^2.1.1",
"isbot": "^5.1.17",
"js-base64": "^3.7.7",
"ramda": "^0.30.1",
"react": "^19.0.0",
"react-dom": "^19.0.0",
"react-router": "^7.2.0",
"yup": "^1.6.1"
},
"devDependencies": {
"@react-router/dev": "^7.2.0",
"@tailwindcss/vite": "^4.0.0",
"prettier": "^3.5.1",
"tailwindcss": "^4.0.0",
"vite": "^5.4.11"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@@ -1,5 +0,0 @@
export default {
// Config options...
// Server-side render by default, to enable SPA mode set this to `false`
ssr: false,
}

View File

@@ -1,13 +0,0 @@
import path from 'path'
import { reactRouter } from '@react-router/dev/vite'
import { defineConfig } from 'vite'
import tailwindcss from '@tailwindcss/vite'
export default defineConfig({
plugins: [reactRouter(), tailwindcss()],
resolve: {
alias: {
'~': path.resolve(__dirname, './app'),
},
},
})