Merge pull request #1 from abhi1693/jarvis/orval-types
Use Orval types directly + repo hygiene
This commit is contained in:
25
.gitignore
vendored
25
.gitignore
vendored
@@ -1,20 +1,15 @@
|
|||||||
# OS / IDE
|
|
||||||
.idea/
|
|
||||||
.DS_Store
|
|
||||||
|
|
||||||
# Python
|
# Python
|
||||||
backend/.venv/
|
__pycache__/
|
||||||
backend/__pycache__/
|
*.py[cod]
|
||||||
backend/.pytest_cache/
|
|
||||||
backend/.env
|
|
||||||
|
|
||||||
# Node
|
# Node / Next
|
||||||
frontend/node_modules/
|
node_modules/
|
||||||
frontend/.next/
|
.next/
|
||||||
frontend/.env.local
|
|
||||||
|
|
||||||
# Logs
|
# Env
|
||||||
*.log
|
.env
|
||||||
|
.env.local
|
||||||
|
|
||||||
# Local run logs
|
# IDE
|
||||||
|
.idea/
|
||||||
.runlogs/
|
.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 { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { normalizeDepartments, normalizeEmployees } from "@/lib/normalize";
|
|
||||||
import { Select } from "@/components/ui/select";
|
import { Select } from "@/components/ui/select";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -20,10 +20,10 @@ export default function DepartmentsPage() {
|
|||||||
const [headId, setHeadId] = useState<string>("");
|
const [headId, setHeadId] = useState<string>("");
|
||||||
|
|
||||||
const departments = useListDepartmentsDepartmentsGet();
|
const departments = useListDepartmentsDepartmentsGet();
|
||||||
const departmentList = normalizeDepartments(departments.data);
|
const departmentList = departments.data ?? [];
|
||||||
const employees = useListEmployeesEmployeesGet();
|
const employees = useListEmployeesEmployeesGet();
|
||||||
|
|
||||||
const employeeList = normalizeEmployees(employees.data);
|
const employeeList = employees.data ?? [];
|
||||||
|
|
||||||
const createDepartment = useCreateDepartmentDepartmentsPost({
|
const createDepartment = useCreateDepartmentDepartmentsPost({
|
||||||
mutation: {
|
mutation: {
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { useState } from "react";
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { normalizeAgentOnboardings, normalizeDepartments, normalizeEmployees, normalizeEmploymentActions, normalizeHeadcountRequests } from "@/lib/normalize";
|
|
||||||
import { Select } from "@/components/ui/select";
|
import { Select } from "@/components/ui/select";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
|
||||||
@@ -22,16 +22,16 @@ import { useListDepartmentsDepartmentsGet, useListEmployeesEmployeesGet } from "
|
|||||||
|
|
||||||
export default function HRPage() {
|
export default function HRPage() {
|
||||||
const departments = useListDepartmentsDepartmentsGet();
|
const departments = useListDepartmentsDepartmentsGet();
|
||||||
const departmentList = normalizeDepartments(departments.data);
|
const departmentList = departments.data ?? [];
|
||||||
const employees = useListEmployeesEmployeesGet();
|
const employees = useListEmployeesEmployeesGet();
|
||||||
const employeeList = normalizeEmployees(employees.data);
|
const employeeList = employees.data ?? [];
|
||||||
|
|
||||||
const headcount = useListHeadcountRequestsHrHeadcountGet();
|
const headcount = useListHeadcountRequestsHrHeadcountGet();
|
||||||
const actions = useListEmploymentActionsHrActionsGet();
|
const actions = useListEmploymentActionsHrActionsGet();
|
||||||
const onboarding = useListAgentOnboardingHrOnboardingGet();
|
const onboarding = useListAgentOnboardingHrOnboardingGet();
|
||||||
const headcountList = normalizeHeadcountRequests(headcount.data);
|
const headcountList = headcount.data ?? [];
|
||||||
const actionList = normalizeEmploymentActions(actions.data);
|
const actionList = actions.data ?? [];
|
||||||
const onboardingList = normalizeAgentOnboardings(onboarding.data);
|
const onboardingList = onboarding.data ?? [];
|
||||||
|
|
||||||
const [hcDeptId, setHcDeptId] = useState<string>("");
|
const [hcDeptId, setHcDeptId] = useState<string>("");
|
||||||
const [hcManagerId, setHcManagerId] = 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 { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Input } from "@/components/ui/input";
|
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 { Select } from "@/components/ui/select";
|
||||||
|
|
||||||
import { useCreateProjectProjectsPost, useListProjectsProjectsGet } from "@/api/generated/projects/projects";
|
import { useCreateProjectProjectsPost, useListProjectsProjectsGet } from "@/api/generated/projects/projects";
|
||||||
@@ -16,12 +16,12 @@ import { useListActivitiesActivitiesGet } from "@/api/generated/activities/activ
|
|||||||
|
|
||||||
export default function Home() {
|
export default function Home() {
|
||||||
const projects = useListProjectsProjectsGet();
|
const projects = useListProjectsProjectsGet();
|
||||||
const projectList = normalizeProjects(projects.data);
|
const projectList = projects.data ?? [];
|
||||||
const departments = useListDepartmentsDepartmentsGet();
|
const departments = useListDepartmentsDepartmentsGet();
|
||||||
const departmentList = normalizeDepartments(departments.data);
|
const departmentList = departments.data ?? [];
|
||||||
const employees = useListEmployeesEmployeesGet();
|
const employees = useListEmployeesEmployeesGet();
|
||||||
const activities = useListActivitiesActivitiesGet({ limit: 20 });
|
const activities = useListActivitiesActivitiesGet({ limit: 20 });
|
||||||
const employeeList = normalizeEmployees(employees.data);
|
const employeeList = employees.data ?? [];
|
||||||
const activityList = normalizeActivities(activities.data);
|
const activityList = normalizeActivities(activities.data);
|
||||||
|
|
||||||
const [projectName, setProjectName] = useState("");
|
const [projectName, setProjectName] = useState("");
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { Button } from "@/components/ui/button";
|
|||||||
import { Badge } from "@/components/ui/badge";
|
import { Badge } from "@/components/ui/badge";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { normalizeDepartments, normalizeEmployees } from "@/lib/normalize";
|
|
||||||
import { Select } from "@/components/ui/select";
|
import { Select } from "@/components/ui/select";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
@@ -24,8 +24,8 @@ export default function PeoplePage() {
|
|||||||
|
|
||||||
const employees = useListEmployeesEmployeesGet();
|
const employees = useListEmployeesEmployeesGet();
|
||||||
const departments = useListDepartmentsDepartmentsGet();
|
const departments = useListDepartmentsDepartmentsGet();
|
||||||
const departmentList = normalizeDepartments(departments.data);
|
const departmentList = useMemo(() => departments.data ?? [], [departments.data]);
|
||||||
const employeeList = normalizeEmployees(employees.data);
|
const employeeList = useMemo(() => employees.data ?? [], [employees.data]);
|
||||||
|
|
||||||
const createEmployee = useCreateEmployeeEmployeesPost({
|
const createEmployee = useCreateEmployeeEmployeesPost({
|
||||||
mutation: {
|
mutation: {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { useParams } from "next/navigation";
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { normalizeEmployees, normalizeProjectMembers, normalizeProjects, normalizeTaskComments, normalizeTasks } from "@/lib/normalize";
|
|
||||||
import { Select } from "@/components/ui/select";
|
import { Select } from "@/components/ui/select";
|
||||||
import { Textarea } from "@/components/ui/textarea";
|
import { Textarea } from "@/components/ui/textarea";
|
||||||
|
|
||||||
@@ -34,14 +34,14 @@ export default function ProjectDetailPage() {
|
|||||||
const projectId = Number(params?.id);
|
const projectId = Number(params?.id);
|
||||||
|
|
||||||
const projects = useListProjectsProjectsGet();
|
const projects = useListProjectsProjectsGet();
|
||||||
const projectList = normalizeProjects(projects.data);
|
const projectList = projects.data ?? [];
|
||||||
const project = projectList.find((p) => p.id === projectId);
|
const project = projectList.find((p) => p.id === projectId);
|
||||||
|
|
||||||
const employees = useListEmployeesEmployeesGet();
|
const employees = useListEmployeesEmployeesGet();
|
||||||
const employeeList = normalizeEmployees(employees.data);
|
const employeeList = employees.data ?? [];
|
||||||
|
|
||||||
const members = useListProjectMembersProjectsProjectIdMembersGet(projectId);
|
const members = useListProjectMembersProjectsProjectIdMembersGet(projectId);
|
||||||
const memberList = normalizeProjectMembers(members.data);
|
const memberList = members.data ?? [];
|
||||||
const addMember = useAddProjectMemberProjectsProjectIdMembersPost({
|
const addMember = useAddProjectMemberProjectsProjectIdMembersPost({
|
||||||
mutation: { onSuccess: () => members.refetch() },
|
mutation: { onSuccess: () => members.refetch() },
|
||||||
});
|
});
|
||||||
@@ -53,7 +53,7 @@ export default function ProjectDetailPage() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const tasks = useListTasksTasksGet({ project_id: projectId });
|
const tasks = useListTasksTasksGet({ project_id: projectId });
|
||||||
const taskList = normalizeTasks(tasks.data);
|
const taskList = tasks.data ?? [];
|
||||||
const createTask = useCreateTaskTasksPost({
|
const createTask = useCreateTaskTasksPost({
|
||||||
mutation: { onSuccess: () => tasks.refetch() },
|
mutation: { onSuccess: () => tasks.refetch() },
|
||||||
});
|
});
|
||||||
@@ -76,7 +76,7 @@ export default function ProjectDetailPage() {
|
|||||||
{ task_id: commentTaskId ?? 0 },
|
{ task_id: commentTaskId ?? 0 },
|
||||||
{ query: { enabled: Boolean(commentTaskId) } },
|
{ query: { enabled: Boolean(commentTaskId) } },
|
||||||
);
|
);
|
||||||
const commentList = normalizeTaskComments(comments.data);
|
const commentList = comments.data ?? [];
|
||||||
const addComment = useCreateTaskCommentTaskCommentsPost({
|
const addComment = useCreateTaskCommentTaskCommentsPost({
|
||||||
mutation: {
|
mutation: {
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import styles from "@/app/_components/Shell.module.css";
|
|||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Input } from "@/components/ui/input";
|
import { Input } from "@/components/ui/input";
|
||||||
import { normalizeProjects } from "@/lib/normalize";
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
useCreateProjectProjectsPost,
|
useCreateProjectProjectsPost,
|
||||||
@@ -18,7 +17,7 @@ export default function ProjectsPage() {
|
|||||||
const [name, setName] = useState("");
|
const [name, setName] = useState("");
|
||||||
|
|
||||||
const projects = useListProjectsProjectsGet();
|
const projects = useListProjectsProjectsGet();
|
||||||
const projectList = normalizeProjects(projects.data);
|
const projectList = projects.data ?? [];
|
||||||
const createProject = useCreateProjectProjectsPost({
|
const createProject = useCreateProjectProjectsPost({
|
||||||
mutation: {
|
mutation: {
|
||||||
onSuccess: () => {
|
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 = {
|
export type Activity = {
|
||||||
id?: number;
|
id?: number;
|
||||||
actor_employee_id?: number | null;
|
actor_employee_id?: number | null;
|
||||||
@@ -10,59 +12,6 @@ export type Activity = {
|
|||||||
payload?: unknown;
|
payload?: unknown;
|
||||||
created_at?: string;
|
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[] {
|
export function normalizeActivities(data: unknown): Activity[] {
|
||||||
if (Array.isArray(data)) return data as Activity[];
|
if (Array.isArray(data)) return data as Activity[];
|
||||||
@@ -72,39 +21,3 @@ export function normalizeActivities(data: unknown): Activity[] {
|
|||||||
}
|
}
|
||||||
return [];
|
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