chore(frontend): use Orval types directly; drop normalize hacks
This commit is contained in:
25
.gitignore
vendored
25
.gitignore
vendored
@@ -1,20 +1,15 @@
|
||||
# OS / IDE
|
||||
.idea/
|
||||
.DS_Store
|
||||
|
||||
# Python
|
||||
backend/.venv/
|
||||
backend/__pycache__/
|
||||
backend/.pytest_cache/
|
||||
backend/.env
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
|
||||
# Node
|
||||
frontend/node_modules/
|
||||
frontend/.next/
|
||||
frontend/.env.local
|
||||
# Node / Next
|
||||
node_modules/
|
||||
.next/
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
# Env
|
||||
.env
|
||||
.env.local
|
||||
|
||||
# Local run logs
|
||||
# IDE
|
||||
.idea/
|
||||
.runlogs/
|
||||
|
||||
4
backend/.gitignore
vendored
Normal file
4
backend/.gitignore
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
.env
|
||||
.venv/
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -5,7 +5,7 @@ import { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { normalizeDepartments, normalizeEmployees } from "@/lib/normalize";
|
||||
|
||||
import { Select } from "@/components/ui/select";
|
||||
|
||||
import {
|
||||
@@ -20,10 +20,10 @@ export default function DepartmentsPage() {
|
||||
const [headId, setHeadId] = useState<string>("");
|
||||
|
||||
const departments = useListDepartmentsDepartmentsGet();
|
||||
const departmentList = normalizeDepartments(departments.data);
|
||||
const departmentList = departments.data ?? [];
|
||||
const employees = useListEmployeesEmployeesGet();
|
||||
|
||||
const employeeList = normalizeEmployees(employees.data);
|
||||
const employeeList = employees.data ?? [];
|
||||
|
||||
const createDepartment = useCreateDepartmentDepartmentsPost({
|
||||
mutation: {
|
||||
|
||||
@@ -5,7 +5,7 @@ import { useState } from "react";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { normalizeAgentOnboardings, normalizeDepartments, normalizeEmployees, normalizeEmploymentActions, normalizeHeadcountRequests } from "@/lib/normalize";
|
||||
|
||||
import { Select } from "@/components/ui/select";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
|
||||
@@ -22,16 +22,16 @@ import { useListDepartmentsDepartmentsGet, useListEmployeesEmployeesGet } from "
|
||||
|
||||
export default function HRPage() {
|
||||
const departments = useListDepartmentsDepartmentsGet();
|
||||
const departmentList = normalizeDepartments(departments.data);
|
||||
const departmentList = departments.data ?? [];
|
||||
const employees = useListEmployeesEmployeesGet();
|
||||
const employeeList = normalizeEmployees(employees.data);
|
||||
const employeeList = employees.data ?? [];
|
||||
|
||||
const headcount = useListHeadcountRequestsHrHeadcountGet();
|
||||
const actions = useListEmploymentActionsHrActionsGet();
|
||||
const onboarding = useListAgentOnboardingHrOnboardingGet();
|
||||
const headcountList = normalizeHeadcountRequests(headcount.data);
|
||||
const actionList = normalizeEmploymentActions(actions.data);
|
||||
const onboardingList = normalizeAgentOnboardings(onboarding.data);
|
||||
const headcountList = headcount.data ?? [];
|
||||
const actionList = actions.data ?? [];
|
||||
const onboardingList = onboarding.data ?? [];
|
||||
|
||||
const [hcDeptId, setHcDeptId] = useState<string>("");
|
||||
const [hcManagerId, setHcManagerId] = useState<string>("");
|
||||
|
||||
@@ -6,7 +6,7 @@ import styles from "@/app/_components/Shell.module.css";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { normalizeActivities, normalizeDepartments, normalizeEmployees, normalizeProjects } from "@/lib/normalize";
|
||||
import { normalizeActivities } from "@/lib/normalize";
|
||||
import { Select } from "@/components/ui/select";
|
||||
|
||||
import { useCreateProjectProjectsPost, useListProjectsProjectsGet } from "@/api/generated/projects/projects";
|
||||
@@ -16,12 +16,12 @@ import { useListActivitiesActivitiesGet } from "@/api/generated/activities/activ
|
||||
|
||||
export default function Home() {
|
||||
const projects = useListProjectsProjectsGet();
|
||||
const projectList = normalizeProjects(projects.data);
|
||||
const projectList = projects.data ?? [];
|
||||
const departments = useListDepartmentsDepartmentsGet();
|
||||
const departmentList = normalizeDepartments(departments.data);
|
||||
const departmentList = departments.data ?? [];
|
||||
const employees = useListEmployeesEmployeesGet();
|
||||
const activities = useListActivitiesActivitiesGet({ limit: 20 });
|
||||
const employeeList = normalizeEmployees(employees.data);
|
||||
const employeeList = employees.data ?? [];
|
||||
const activityList = normalizeActivities(activities.data);
|
||||
|
||||
const [projectName, setProjectName] = useState("");
|
||||
|
||||
@@ -6,7 +6,7 @@ import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { normalizeDepartments, normalizeEmployees } from "@/lib/normalize";
|
||||
|
||||
import { Select } from "@/components/ui/select";
|
||||
|
||||
import {
|
||||
@@ -24,8 +24,8 @@ export default function PeoplePage() {
|
||||
|
||||
const employees = useListEmployeesEmployeesGet();
|
||||
const departments = useListDepartmentsDepartmentsGet();
|
||||
const departmentList = normalizeDepartments(departments.data);
|
||||
const employeeList = normalizeEmployees(employees.data);
|
||||
const departmentList = departments.data ?? [];
|
||||
const employeeList = employees.data ?? [];
|
||||
|
||||
const createEmployee = useCreateEmployeeEmployeesPost({
|
||||
mutation: {
|
||||
|
||||
@@ -6,7 +6,7 @@ import { useParams } from "next/navigation";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { normalizeEmployees, normalizeProjectMembers, normalizeProjects, normalizeTaskComments, normalizeTasks } from "@/lib/normalize";
|
||||
|
||||
import { Select } from "@/components/ui/select";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
|
||||
@@ -34,14 +34,14 @@ export default function ProjectDetailPage() {
|
||||
const projectId = Number(params?.id);
|
||||
|
||||
const projects = useListProjectsProjectsGet();
|
||||
const projectList = normalizeProjects(projects.data);
|
||||
const projectList = projects.data ?? [];
|
||||
const project = projectList.find((p) => p.id === projectId);
|
||||
|
||||
const employees = useListEmployeesEmployeesGet();
|
||||
const employeeList = normalizeEmployees(employees.data);
|
||||
const employeeList = employees.data ?? [];
|
||||
|
||||
const members = useListProjectMembersProjectsProjectIdMembersGet(projectId);
|
||||
const memberList = normalizeProjectMembers(members.data);
|
||||
const memberList = members.data ?? [];
|
||||
const addMember = useAddProjectMemberProjectsProjectIdMembersPost({
|
||||
mutation: { onSuccess: () => members.refetch() },
|
||||
});
|
||||
@@ -53,7 +53,7 @@ export default function ProjectDetailPage() {
|
||||
});
|
||||
|
||||
const tasks = useListTasksTasksGet({ project_id: projectId });
|
||||
const taskList = normalizeTasks(tasks.data);
|
||||
const taskList = tasks.data ?? [];
|
||||
const createTask = useCreateTaskTasksPost({
|
||||
mutation: { onSuccess: () => tasks.refetch() },
|
||||
});
|
||||
@@ -76,7 +76,7 @@ export default function ProjectDetailPage() {
|
||||
{ task_id: commentTaskId ?? 0 },
|
||||
{ query: { enabled: Boolean(commentTaskId) } },
|
||||
);
|
||||
const commentList = normalizeTaskComments(comments.data);
|
||||
const commentList = comments.data ?? [];
|
||||
const addComment = useCreateTaskCommentTaskCommentsPost({
|
||||
mutation: {
|
||||
onSuccess: () => {
|
||||
|
||||
@@ -7,7 +7,6 @@ import styles from "@/app/_components/Shell.module.css";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { normalizeProjects } from "@/lib/normalize";
|
||||
|
||||
import {
|
||||
useCreateProjectProjectsPost,
|
||||
@@ -18,7 +17,7 @@ export default function ProjectsPage() {
|
||||
const [name, setName] = useState("");
|
||||
|
||||
const projects = useListProjectsProjectsGet();
|
||||
const projectList = normalizeProjects(projects.data);
|
||||
const projectList = projects.data ?? [];
|
||||
const createProject = useCreateProjectProjectsPost({
|
||||
mutation: {
|
||||
onSuccess: () => {
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
export function apiUrl(path: string) {
|
||||
const base = process.env.NEXT_PUBLIC_API_URL;
|
||||
if (!base) throw new Error("NEXT_PUBLIC_API_URL is not set");
|
||||
return `${base}${path}`;
|
||||
}
|
||||
|
||||
export async function apiGet<T>(path: string): Promise<T> {
|
||||
const res = await fetch(apiUrl(path), { cache: "no-store" });
|
||||
if (!res.ok) throw new Error(`GET ${path} failed (${res.status})`);
|
||||
return (await res.json()) as T;
|
||||
}
|
||||
|
||||
export async function apiSend<T>(
|
||||
path: string,
|
||||
opts: { method: "POST" | "PATCH" | "DELETE"; body?: unknown }
|
||||
): Promise<T> {
|
||||
const res = await fetch(apiUrl(path), {
|
||||
method: opts.method,
|
||||
headers: opts.body ? { "Content-Type": "application/json" } : undefined,
|
||||
body: opts.body ? JSON.stringify(opts.body) : undefined,
|
||||
});
|
||||
if (!res.ok) throw new Error(`${opts.method} ${path} failed (${res.status})`);
|
||||
return (await res.json()) as T;
|
||||
}
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { Department } from "@/api/generated/model/department";
|
||||
// NOTE:
|
||||
// Orval-generated hooks already return strongly-typed arrays for most endpoints.
|
||||
// We keep only the Activity type + a tiny normalizer here because Activity is not
|
||||
// currently generated as a model.
|
||||
|
||||
// Local activity shape (not generated as a model)
|
||||
export type Activity = {
|
||||
id?: number;
|
||||
actor_employee_id?: number | null;
|
||||
@@ -10,59 +12,6 @@ export type Activity = {
|
||||
payload?: unknown;
|
||||
created_at?: string;
|
||||
};
|
||||
import type { Employee } from "@/api/generated/model/employee";
|
||||
import type { AgentOnboarding } from "@/api/generated/model/agentOnboarding";
|
||||
import type { EmploymentAction } from "@/api/generated/model/employmentAction";
|
||||
import type { HeadcountRequest } from "@/api/generated/model/headcountRequest";
|
||||
import type { Project } from "@/api/generated/model/project";
|
||||
import type { Task } from "@/api/generated/model/task";
|
||||
import type { ProjectMember } from "@/api/generated/model/projectMember";
|
||||
import type { TaskComment } from "@/api/generated/model/taskComment";
|
||||
|
||||
export function normalizeEmployees(data: unknown): Employee[] {
|
||||
if (Array.isArray(data)) return data as Employee[];
|
||||
if (data && typeof data === "object" && "data" in data) {
|
||||
const maybe = (data as { data?: unknown }).data;
|
||||
if (Array.isArray(maybe)) return maybe as Employee[];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function normalizeDepartments(data: unknown): Department[] {
|
||||
if (Array.isArray(data)) return data as Department[];
|
||||
if (data && typeof data === "object" && "data" in data) {
|
||||
const maybe = (data as { data?: unknown }).data;
|
||||
if (Array.isArray(maybe)) return maybe as Department[];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function normalizeHeadcountRequests(data: unknown): HeadcountRequest[] {
|
||||
if (Array.isArray(data)) return data as HeadcountRequest[];
|
||||
if (data && typeof data === "object" && "data" in data) {
|
||||
const maybe = (data as { data?: unknown }).data;
|
||||
if (Array.isArray(maybe)) return maybe as HeadcountRequest[];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function normalizeEmploymentActions(data: unknown): EmploymentAction[] {
|
||||
if (Array.isArray(data)) return data as EmploymentAction[];
|
||||
if (data && typeof data === "object" && "data" in data) {
|
||||
const maybe = (data as { data?: unknown }).data;
|
||||
if (Array.isArray(maybe)) return maybe as EmploymentAction[];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function normalizeAgentOnboardings(data: unknown): AgentOnboarding[] {
|
||||
if (Array.isArray(data)) return data as AgentOnboarding[];
|
||||
if (data && typeof data === "object" && "data" in data) {
|
||||
const maybe = (data as { data?: unknown }).data;
|
||||
if (Array.isArray(maybe)) return maybe as AgentOnboarding[];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function normalizeActivities(data: unknown): Activity[] {
|
||||
if (Array.isArray(data)) return data as Activity[];
|
||||
@@ -72,39 +21,3 @@ export function normalizeActivities(data: unknown): Activity[] {
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function normalizeProjects(data: unknown): Project[] {
|
||||
if (Array.isArray(data)) return data as Project[];
|
||||
if (data && typeof data === "object" && "data" in data) {
|
||||
const maybe = (data as { data?: unknown }).data;
|
||||
if (Array.isArray(maybe)) return maybe as Project[];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function normalizeTasks(data: unknown): Task[] {
|
||||
if (Array.isArray(data)) return data as Task[];
|
||||
if (data && typeof data === "object" && "data" in data) {
|
||||
const maybe = (data as { data?: unknown }).data;
|
||||
if (Array.isArray(maybe)) return maybe as Task[];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function normalizeTaskComments(data: unknown): TaskComment[] {
|
||||
if (Array.isArray(data)) return data as TaskComment[];
|
||||
if (data && typeof data === "object" && "data" in data) {
|
||||
const maybe = (data as { data?: unknown }).data;
|
||||
if (Array.isArray(maybe)) return maybe as TaskComment[];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
export function normalizeProjectMembers(data: unknown): ProjectMember[] {
|
||||
if (Array.isArray(data)) return data as ProjectMember[];
|
||||
if (data && typeof data === "object" && "data" in data) {
|
||||
const maybe = (data as { data?: unknown }).data;
|
||||
if (Array.isArray(maybe)) return maybe as ProjectMember[];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user