Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Audit360 Hotéis
# Audit360 Motéis

Aplicativo web em React + TypeScript para auditorias de hotéis. O projeto foi criado manualmente com Vite e utiliza um backend simulado via `localStorage`.
Aplicativo web em React + TypeScript para auditorias de motéis. O projeto foi criado manualmente com Vite e utiliza um backend simulado via `localStorage`.

## Scripts

Expand All @@ -13,5 +13,7 @@ Aplicativo web em React + TypeScript para auditorias de hotéis. O projeto foi c
- Dashboard com listagem de auditorias e botão para iniciar novas auditorias.
- Formulários de checklist com opções "Conforme", "Não conforme leve", "Não conforme grave" e upload de fotos.
- Relatórios filtrados por unidade, data e responsável.
- Agenda de reuniões com cadastro de encontros.
- Tela de performance das gestoras (blackbelts) com resumo de auditorias.

As informações são salvas no `localStorage` do navegador e as imagens ficam codificadas em base64.
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/logo.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Audit360 Hotéis</title>
<title>Audit360 Motéis</title>
</head>
<body>
<div id="root"></div>
Expand Down
10 changes: 10 additions & 0 deletions src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import Login from './pages/Login';
import Dashboard from './pages/Dashboard';
import AuditForm from './pages/AuditForm';
import Reports from './pages/Reports';
import Meetings from './pages/Meetings';
import Performance from './pages/Performance';
import Header from './components/Header';
import { useAuth } from './auth';

Expand Down Expand Up @@ -30,6 +32,14 @@ export default function App() {
path="/reports"
element={<PrivateRoute><Reports /></PrivateRoute>}
/>
<Route
path="/meetings"
element={<PrivateRoute><Meetings /></PrivateRoute>}
/>
<Route
path="/performance"
element={<PrivateRoute><Performance /></PrivateRoute>}
/>
</Routes>
</>
);
Expand Down
4 changes: 3 additions & 1 deletion src/components/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ export default function Header() {
const { user, logout } = useAuth();
return (
<header>
<h1>Audit360 Hotéis</h1>
<h1>Audit360 Motéis</h1>
<nav>
<Link to="/">Auditorias</Link>
<Link to="/reports">Relatórios</Link>
<Link to="/meetings">Reuniões</Link>
<Link to="/performance">Performance</Link>
</nav>
<div>
{user && (
Expand Down
55 changes: 55 additions & 0 deletions src/pages/Meetings.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import { useEffect, useState, FormEvent } from 'react';
import { useAuth } from '../auth';
import { Meeting } from '../types';

export default function Meetings() {
const { user } = useAuth();
const [meetings, setMeetings] = useState<Meeting[]>([]);
const [date, setDate] = useState('');
const [subject, setSubject] = useState('');
const [participants, setParticipants] = useState('');

useEffect(() => {
const stored = localStorage.getItem('meetings');
if (stored) setMeetings(JSON.parse(stored));
}, []);

const handleSubmit = (e: FormEvent) => {
e.preventDefault();
const newMeeting: Meeting = {
id: Date.now(),
date,
subject,
participants,
};
const updated = [...meetings, newMeeting];
setMeetings(updated);
localStorage.setItem('meetings', JSON.stringify(updated));
setDate('');
setSubject('');
setParticipants('');
};

return (
<div className="container">
<h2>Reuniões</h2>
{user?.role !== 'Supervisor' && (
<form onSubmit={handleSubmit} style={{ marginBottom: '1rem' }}>
<label>Data</label>
<input type="date" value={date} onChange={(e) => setDate(e.target.value)} required />
<label>Assunto</label>
<input value={subject} onChange={(e) => setSubject(e.target.value)} required />
<label>Participantes</label>
<input value={participants} onChange={(e) => setParticipants(e.target.value)} required />
<button type="submit">Agendar</button>
</form>
)}
{meetings.map((m) => (
<div key={m.id} className="audit-item">
<strong>{m.date}</strong> - {m.subject} - {m.participants}
</div>
))}
{meetings.length === 0 && <p>Nenhuma reunião agendada.</p>}
</div>
);
}
42 changes: 42 additions & 0 deletions src/pages/Performance.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { useEffect, useState } from 'react';
import { Audit } from '../types';

interface Metric {
responsible: string;
total: number;
severe: number;
}

export default function Performance() {
const [metrics, setMetrics] = useState<Metric[]>([]);

useEffect(() => {
const stored = localStorage.getItem('audits');
if (stored) {
const audits: Audit[] = JSON.parse(stored);
const map: Record<string, Metric> = {};
audits.forEach((a) => {
if (!map[a.responsible]) {
map[a.responsible] = { responsible: a.responsible, total: 0, severe: 0 };
}
map[a.responsible].total += 1;
if (a.answers.some((ans) => ans.status === 'Não conforme grave')) {
map[a.responsible].severe += 1;
}
});
setMetrics(Object.values(map));
}
}, []);

return (
<div className="container">
<h2>Performance das Blackbelts</h2>
{metrics.map((m) => (
<div key={m.responsible} className="audit-item">
<strong>{m.responsible}</strong> - Auditorias: {m.total} - Ocorrências graves: {m.severe}
</div>
))}
{metrics.length === 0 && <p>Nenhuma auditoria registrada.</p>}
</div>
);
}
7 changes: 7 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,10 @@ export interface Audit {
responsible: string;
answers: AuditAnswer[];
}

export interface Meeting {
id: number;
date: string;
subject: string;
participants: string;
}