Add Tailwind + shadcn UI primitives; add React Query + Orval client
This commit is contained in:
3
frontend/.eslintignore
Normal file
3
frontend/.eslintignore
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
tailwind.config.*
|
||||||
|
postcss.config.*
|
||||||
|
orval.config.*
|
||||||
@@ -12,6 +12,9 @@ const eslintConfig = defineConfig([
|
|||||||
"out/**",
|
"out/**",
|
||||||
"build/**",
|
"build/**",
|
||||||
"next-env.d.ts",
|
"next-env.d.ts",
|
||||||
|
"tailwind.config.*",
|
||||||
|
"postcss.config.*",
|
||||||
|
"orval.config.*",
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|||||||
26
frontend/orval.config.ts
Normal file
26
frontend/orval.config.ts
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import { defineConfig } from "orval";
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
api: {
|
||||||
|
input: {
|
||||||
|
target: "http://127.0.0.1:8000/openapi.json",
|
||||||
|
},
|
||||||
|
output: {
|
||||||
|
mode: "tags-split",
|
||||||
|
target: "src/api/generated/index.ts",
|
||||||
|
schemas: "src/api/generated/model",
|
||||||
|
client: "fetch",
|
||||||
|
prettier: true,
|
||||||
|
override: {
|
||||||
|
mutator: {
|
||||||
|
path: "src/api/mutator.ts",
|
||||||
|
name: "customFetch",
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
useQuery: true,
|
||||||
|
useMutation: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
2526
frontend/package-lock.json
generated
2526
frontend/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -7,9 +7,11 @@
|
|||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "eslint",
|
"lint": "eslint",
|
||||||
"dev:lan": "next dev --hostname 0.0.0.0 --port 3000"
|
"dev:lan": "next dev --hostname 0.0.0.0 --port 3000",
|
||||||
|
"api:gen": "orval --config ./orval.config.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@tanstack/react-query": "^5.90.20",
|
||||||
"next": "16.1.6",
|
"next": "16.1.6",
|
||||||
"react": "19.2.3",
|
"react": "19.2.3",
|
||||||
"react-dom": "19.2.3"
|
"react-dom": "19.2.3"
|
||||||
@@ -18,8 +20,18 @@
|
|||||||
"@types/node": "^20",
|
"@types/node": "^20",
|
||||||
"@types/react": "^19",
|
"@types/react": "^19",
|
||||||
"@types/react-dom": "^19",
|
"@types/react-dom": "^19",
|
||||||
|
"autoprefixer": "^10.4.24",
|
||||||
|
"class-variance-authority": "^0.7.1",
|
||||||
|
"clsx": "^2.1.1",
|
||||||
"eslint": "^9",
|
"eslint": "^9",
|
||||||
"eslint-config-next": "16.1.6",
|
"eslint-config-next": "16.1.6",
|
||||||
|
"lucide-react": "^0.563.0",
|
||||||
|
"orval": "^8.2.0",
|
||||||
|
"postcss": "^8.5.6",
|
||||||
|
"prettier": "^3.8.1",
|
||||||
|
"tailwind-merge": "^3.4.0",
|
||||||
|
"tailwindcss": "^3.4.17",
|
||||||
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"typescript": "^5"
|
"typescript": "^5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
6
frontend/postcss.config.js
Normal file
6
frontend/postcss.config.js
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: {
|
||||||
|
tailwindcss: {},
|
||||||
|
autoprefixer: {},
|
||||||
|
},
|
||||||
|
}
|
||||||
69
frontend/src/api/generated/activities/activities.ts
Normal file
69
frontend/src/api/generated/activities/activities.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
import type {
|
||||||
|
HTTPValidationError,
|
||||||
|
ListActivitiesActivitiesGetParams,
|
||||||
|
} from ".././model";
|
||||||
|
|
||||||
|
import { customFetch } from "../../mutator";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary List Activities
|
||||||
|
*/
|
||||||
|
export type listActivitiesActivitiesGetResponse200 = {
|
||||||
|
data: unknown;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listActivitiesActivitiesGetResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listActivitiesActivitiesGetResponseSuccess =
|
||||||
|
listActivitiesActivitiesGetResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type listActivitiesActivitiesGetResponseError =
|
||||||
|
listActivitiesActivitiesGetResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listActivitiesActivitiesGetResponse =
|
||||||
|
| listActivitiesActivitiesGetResponseSuccess
|
||||||
|
| listActivitiesActivitiesGetResponseError;
|
||||||
|
|
||||||
|
export const getListActivitiesActivitiesGetUrl = (
|
||||||
|
params?: ListActivitiesActivitiesGetParams,
|
||||||
|
) => {
|
||||||
|
const normalizedParams = new URLSearchParams();
|
||||||
|
|
||||||
|
Object.entries(params || {}).forEach(([key, value]) => {
|
||||||
|
if (value !== undefined) {
|
||||||
|
normalizedParams.append(key, value === null ? "null" : value.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const stringifiedParams = normalizedParams.toString();
|
||||||
|
|
||||||
|
return stringifiedParams.length > 0
|
||||||
|
? `/activities?${stringifiedParams}`
|
||||||
|
: `/activities`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const listActivitiesActivitiesGet = async (
|
||||||
|
params?: ListActivitiesActivitiesGetParams,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<listActivitiesActivitiesGetResponse> => {
|
||||||
|
return customFetch<listActivitiesActivitiesGetResponse>(
|
||||||
|
getListActivitiesActivitiesGetUrl(params),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
33
frontend/src/api/generated/default/default.ts
Normal file
33
frontend/src/api/generated/default/default.ts
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
import { customFetch } from "../../mutator";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Health
|
||||||
|
*/
|
||||||
|
export type healthHealthGetResponse200 = {
|
||||||
|
data: unknown;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type healthHealthGetResponseSuccess = healthHealthGetResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type healthHealthGetResponse = healthHealthGetResponseSuccess;
|
||||||
|
|
||||||
|
export const getHealthHealthGetUrl = () => {
|
||||||
|
return `/health`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const healthHealthGet = async (
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<healthHealthGetResponse> => {
|
||||||
|
return customFetch<healthHealthGetResponse>(getHealthHealthGetUrl(), {
|
||||||
|
...options,
|
||||||
|
method: "GET",
|
||||||
|
});
|
||||||
|
};
|
||||||
216
frontend/src/api/generated/hr/hr.ts
Normal file
216
frontend/src/api/generated/hr/hr.ts
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
import type {
|
||||||
|
EmploymentAction,
|
||||||
|
EmploymentActionCreate,
|
||||||
|
HTTPValidationError,
|
||||||
|
HeadcountRequest,
|
||||||
|
HeadcountRequestCreate,
|
||||||
|
HeadcountRequestUpdate,
|
||||||
|
} from ".././model";
|
||||||
|
|
||||||
|
import { customFetch } from "../../mutator";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary List Headcount Requests
|
||||||
|
*/
|
||||||
|
export type listHeadcountRequestsHrHeadcountGetResponse200 = {
|
||||||
|
data: HeadcountRequest[];
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listHeadcountRequestsHrHeadcountGetResponseSuccess =
|
||||||
|
listHeadcountRequestsHrHeadcountGetResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type listHeadcountRequestsHrHeadcountGetResponse =
|
||||||
|
listHeadcountRequestsHrHeadcountGetResponseSuccess;
|
||||||
|
|
||||||
|
export const getListHeadcountRequestsHrHeadcountGetUrl = () => {
|
||||||
|
return `/hr/headcount`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const listHeadcountRequestsHrHeadcountGet = async (
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<listHeadcountRequestsHrHeadcountGetResponse> => {
|
||||||
|
return customFetch<listHeadcountRequestsHrHeadcountGetResponse>(
|
||||||
|
getListHeadcountRequestsHrHeadcountGetUrl(),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Create Headcount Request
|
||||||
|
*/
|
||||||
|
export type createHeadcountRequestHrHeadcountPostResponse200 = {
|
||||||
|
data: HeadcountRequest;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createHeadcountRequestHrHeadcountPostResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createHeadcountRequestHrHeadcountPostResponseSuccess =
|
||||||
|
createHeadcountRequestHrHeadcountPostResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type createHeadcountRequestHrHeadcountPostResponseError =
|
||||||
|
createHeadcountRequestHrHeadcountPostResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createHeadcountRequestHrHeadcountPostResponse =
|
||||||
|
| createHeadcountRequestHrHeadcountPostResponseSuccess
|
||||||
|
| createHeadcountRequestHrHeadcountPostResponseError;
|
||||||
|
|
||||||
|
export const getCreateHeadcountRequestHrHeadcountPostUrl = () => {
|
||||||
|
return `/hr/headcount`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createHeadcountRequestHrHeadcountPost = async (
|
||||||
|
headcountRequestCreate: HeadcountRequestCreate,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<createHeadcountRequestHrHeadcountPostResponse> => {
|
||||||
|
return customFetch<createHeadcountRequestHrHeadcountPostResponse>(
|
||||||
|
getCreateHeadcountRequestHrHeadcountPostUrl(),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||||
|
body: JSON.stringify(headcountRequestCreate),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Update Headcount Request
|
||||||
|
*/
|
||||||
|
export type updateHeadcountRequestHrHeadcountRequestIdPatchResponse200 = {
|
||||||
|
data: HeadcountRequest;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateHeadcountRequestHrHeadcountRequestIdPatchResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateHeadcountRequestHrHeadcountRequestIdPatchResponseSuccess =
|
||||||
|
updateHeadcountRequestHrHeadcountRequestIdPatchResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type updateHeadcountRequestHrHeadcountRequestIdPatchResponseError =
|
||||||
|
updateHeadcountRequestHrHeadcountRequestIdPatchResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateHeadcountRequestHrHeadcountRequestIdPatchResponse =
|
||||||
|
| updateHeadcountRequestHrHeadcountRequestIdPatchResponseSuccess
|
||||||
|
| updateHeadcountRequestHrHeadcountRequestIdPatchResponseError;
|
||||||
|
|
||||||
|
export const getUpdateHeadcountRequestHrHeadcountRequestIdPatchUrl = (
|
||||||
|
requestId: number,
|
||||||
|
) => {
|
||||||
|
return `/hr/headcount/${requestId}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateHeadcountRequestHrHeadcountRequestIdPatch = async (
|
||||||
|
requestId: number,
|
||||||
|
headcountRequestUpdate: HeadcountRequestUpdate,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<updateHeadcountRequestHrHeadcountRequestIdPatchResponse> => {
|
||||||
|
return customFetch<updateHeadcountRequestHrHeadcountRequestIdPatchResponse>(
|
||||||
|
getUpdateHeadcountRequestHrHeadcountRequestIdPatchUrl(requestId),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "PATCH",
|
||||||
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||||
|
body: JSON.stringify(headcountRequestUpdate),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary List Employment Actions
|
||||||
|
*/
|
||||||
|
export type listEmploymentActionsHrActionsGetResponse200 = {
|
||||||
|
data: EmploymentAction[];
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listEmploymentActionsHrActionsGetResponseSuccess =
|
||||||
|
listEmploymentActionsHrActionsGetResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type listEmploymentActionsHrActionsGetResponse =
|
||||||
|
listEmploymentActionsHrActionsGetResponseSuccess;
|
||||||
|
|
||||||
|
export const getListEmploymentActionsHrActionsGetUrl = () => {
|
||||||
|
return `/hr/actions`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const listEmploymentActionsHrActionsGet = async (
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<listEmploymentActionsHrActionsGetResponse> => {
|
||||||
|
return customFetch<listEmploymentActionsHrActionsGetResponse>(
|
||||||
|
getListEmploymentActionsHrActionsGetUrl(),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Create Employment Action
|
||||||
|
*/
|
||||||
|
export type createEmploymentActionHrActionsPostResponse200 = {
|
||||||
|
data: EmploymentAction;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createEmploymentActionHrActionsPostResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createEmploymentActionHrActionsPostResponseSuccess =
|
||||||
|
createEmploymentActionHrActionsPostResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type createEmploymentActionHrActionsPostResponseError =
|
||||||
|
createEmploymentActionHrActionsPostResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createEmploymentActionHrActionsPostResponse =
|
||||||
|
| createEmploymentActionHrActionsPostResponseSuccess
|
||||||
|
| createEmploymentActionHrActionsPostResponseError;
|
||||||
|
|
||||||
|
export const getCreateEmploymentActionHrActionsPostUrl = () => {
|
||||||
|
return `/hr/actions`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createEmploymentActionHrActionsPost = async (
|
||||||
|
employmentActionCreate: EmploymentActionCreate,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<createEmploymentActionHrActionsPostResponse> => {
|
||||||
|
return customFetch<createEmploymentActionHrActionsPostResponse>(
|
||||||
|
getCreateEmploymentActionHrActionsPostUrl(),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||||
|
body: JSON.stringify(employmentActionCreate),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
12
frontend/src/api/generated/model/department.ts
Normal file
12
frontend/src/api/generated/model/department.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface Department {
|
||||||
|
id?: number | null;
|
||||||
|
name: string;
|
||||||
|
head_employee_id?: number | null;
|
||||||
|
}
|
||||||
11
frontend/src/api/generated/model/departmentCreate.ts
Normal file
11
frontend/src/api/generated/model/departmentCreate.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface DepartmentCreate {
|
||||||
|
name: string;
|
||||||
|
head_employee_id?: number | null;
|
||||||
|
}
|
||||||
11
frontend/src/api/generated/model/departmentUpdate.ts
Normal file
11
frontend/src/api/generated/model/departmentUpdate.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface DepartmentUpdate {
|
||||||
|
name?: string | null;
|
||||||
|
head_employee_id?: number | null;
|
||||||
|
}
|
||||||
16
frontend/src/api/generated/model/employee.ts
Normal file
16
frontend/src/api/generated/model/employee.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface Employee {
|
||||||
|
id?: number | null;
|
||||||
|
name: string;
|
||||||
|
employee_type: string;
|
||||||
|
department_id?: number | null;
|
||||||
|
manager_id?: number | null;
|
||||||
|
title?: string | null;
|
||||||
|
status?: string;
|
||||||
|
}
|
||||||
15
frontend/src/api/generated/model/employeeCreate.ts
Normal file
15
frontend/src/api/generated/model/employeeCreate.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface EmployeeCreate {
|
||||||
|
name: string;
|
||||||
|
employee_type: string;
|
||||||
|
department_id?: number | null;
|
||||||
|
manager_id?: number | null;
|
||||||
|
title?: string | null;
|
||||||
|
status?: string;
|
||||||
|
}
|
||||||
15
frontend/src/api/generated/model/employeeUpdate.ts
Normal file
15
frontend/src/api/generated/model/employeeUpdate.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface EmployeeUpdate {
|
||||||
|
name?: string | null;
|
||||||
|
employee_type?: string | null;
|
||||||
|
department_id?: number | null;
|
||||||
|
manager_id?: number | null;
|
||||||
|
title?: string | null;
|
||||||
|
status?: string | null;
|
||||||
|
}
|
||||||
15
frontend/src/api/generated/model/employmentAction.ts
Normal file
15
frontend/src/api/generated/model/employmentAction.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface EmploymentAction {
|
||||||
|
id?: number | null;
|
||||||
|
employee_id: number;
|
||||||
|
issued_by_employee_id: number;
|
||||||
|
action_type: string;
|
||||||
|
notes?: string | null;
|
||||||
|
created_at?: string;
|
||||||
|
}
|
||||||
13
frontend/src/api/generated/model/employmentActionCreate.ts
Normal file
13
frontend/src/api/generated/model/employmentActionCreate.ts
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface EmploymentActionCreate {
|
||||||
|
employee_id: number;
|
||||||
|
issued_by_employee_id: number;
|
||||||
|
action_type: string;
|
||||||
|
notes?: string | null;
|
||||||
|
}
|
||||||
11
frontend/src/api/generated/model/hTTPValidationError.ts
Normal file
11
frontend/src/api/generated/model/hTTPValidationError.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
import type { ValidationError } from "./validationError";
|
||||||
|
|
||||||
|
export interface HTTPValidationError {
|
||||||
|
detail?: ValidationError[];
|
||||||
|
}
|
||||||
18
frontend/src/api/generated/model/headcountRequest.ts
Normal file
18
frontend/src/api/generated/model/headcountRequest.ts
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface HeadcountRequest {
|
||||||
|
id?: number | null;
|
||||||
|
department_id: number;
|
||||||
|
requested_by_manager_id: number;
|
||||||
|
role_title: string;
|
||||||
|
employee_type: string;
|
||||||
|
quantity?: number;
|
||||||
|
justification?: string | null;
|
||||||
|
status?: string;
|
||||||
|
created_at?: string;
|
||||||
|
}
|
||||||
15
frontend/src/api/generated/model/headcountRequestCreate.ts
Normal file
15
frontend/src/api/generated/model/headcountRequestCreate.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface HeadcountRequestCreate {
|
||||||
|
department_id: number;
|
||||||
|
requested_by_manager_id: number;
|
||||||
|
role_title: string;
|
||||||
|
employee_type: string;
|
||||||
|
quantity?: number;
|
||||||
|
justification?: string | null;
|
||||||
|
}
|
||||||
11
frontend/src/api/generated/model/headcountRequestUpdate.ts
Normal file
11
frontend/src/api/generated/model/headcountRequestUpdate.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface HeadcountRequestUpdate {
|
||||||
|
status?: string | null;
|
||||||
|
justification?: string | null;
|
||||||
|
}
|
||||||
31
frontend/src/api/generated/model/index.ts
Normal file
31
frontend/src/api/generated/model/index.ts
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export * from "./department";
|
||||||
|
export * from "./departmentCreate";
|
||||||
|
export * from "./departmentUpdate";
|
||||||
|
export * from "./employee";
|
||||||
|
export * from "./employeeCreate";
|
||||||
|
export * from "./employeeUpdate";
|
||||||
|
export * from "./employmentAction";
|
||||||
|
export * from "./employmentActionCreate";
|
||||||
|
export * from "./headcountRequest";
|
||||||
|
export * from "./headcountRequestCreate";
|
||||||
|
export * from "./headcountRequestUpdate";
|
||||||
|
export * from "./hTTPValidationError";
|
||||||
|
export * from "./listActivitiesActivitiesGetParams";
|
||||||
|
export * from "./listTaskCommentsTaskCommentsGetParams";
|
||||||
|
export * from "./listTasksTasksGetParams";
|
||||||
|
export * from "./project";
|
||||||
|
export * from "./projectCreate";
|
||||||
|
export * from "./projectUpdate";
|
||||||
|
export * from "./task";
|
||||||
|
export * from "./taskComment";
|
||||||
|
export * from "./taskCommentCreate";
|
||||||
|
export * from "./taskCreate";
|
||||||
|
export * from "./taskUpdate";
|
||||||
|
export * from "./validationError";
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type ListActivitiesActivitiesGetParams = {
|
||||||
|
limit?: number;
|
||||||
|
};
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type ListTaskCommentsTaskCommentsGetParams = {
|
||||||
|
task_id: number;
|
||||||
|
};
|
||||||
10
frontend/src/api/generated/model/listTasksTasksGetParams.ts
Normal file
10
frontend/src/api/generated/model/listTasksTasksGetParams.ts
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export type ListTasksTasksGetParams = {
|
||||||
|
project_id?: number | null;
|
||||||
|
};
|
||||||
12
frontend/src/api/generated/model/project.ts
Normal file
12
frontend/src/api/generated/model/project.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface Project {
|
||||||
|
id?: number | null;
|
||||||
|
name: string;
|
||||||
|
status?: string;
|
||||||
|
}
|
||||||
11
frontend/src/api/generated/model/projectCreate.ts
Normal file
11
frontend/src/api/generated/model/projectCreate.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ProjectCreate {
|
||||||
|
name: string;
|
||||||
|
status?: string;
|
||||||
|
}
|
||||||
11
frontend/src/api/generated/model/projectUpdate.ts
Normal file
11
frontend/src/api/generated/model/projectUpdate.ts
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ProjectUpdate {
|
||||||
|
name?: string | null;
|
||||||
|
status?: string | null;
|
||||||
|
}
|
||||||
19
frontend/src/api/generated/model/task.ts
Normal file
19
frontend/src/api/generated/model/task.ts
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface Task {
|
||||||
|
id?: number | null;
|
||||||
|
project_id: number;
|
||||||
|
title: string;
|
||||||
|
description?: string | null;
|
||||||
|
status?: string;
|
||||||
|
assignee_employee_id?: number | null;
|
||||||
|
reviewer_employee_id?: number | null;
|
||||||
|
created_by_employee_id?: number | null;
|
||||||
|
created_at?: string;
|
||||||
|
updated_at?: string;
|
||||||
|
}
|
||||||
14
frontend/src/api/generated/model/taskComment.ts
Normal file
14
frontend/src/api/generated/model/taskComment.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface TaskComment {
|
||||||
|
id?: number | null;
|
||||||
|
task_id: number;
|
||||||
|
author_employee_id?: number | null;
|
||||||
|
body: string;
|
||||||
|
created_at?: string;
|
||||||
|
}
|
||||||
12
frontend/src/api/generated/model/taskCommentCreate.ts
Normal file
12
frontend/src/api/generated/model/taskCommentCreate.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface TaskCommentCreate {
|
||||||
|
task_id: number;
|
||||||
|
author_employee_id?: number | null;
|
||||||
|
body: string;
|
||||||
|
}
|
||||||
16
frontend/src/api/generated/model/taskCreate.ts
Normal file
16
frontend/src/api/generated/model/taskCreate.ts
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface TaskCreate {
|
||||||
|
project_id: number;
|
||||||
|
title: string;
|
||||||
|
description?: string | null;
|
||||||
|
status?: string;
|
||||||
|
assignee_employee_id?: number | null;
|
||||||
|
reviewer_employee_id?: number | null;
|
||||||
|
created_by_employee_id?: number | null;
|
||||||
|
}
|
||||||
14
frontend/src/api/generated/model/taskUpdate.ts
Normal file
14
frontend/src/api/generated/model/taskUpdate.ts
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface TaskUpdate {
|
||||||
|
title?: string | null;
|
||||||
|
description?: string | null;
|
||||||
|
status?: string | null;
|
||||||
|
assignee_employee_id?: number | null;
|
||||||
|
reviewer_employee_id?: number | null;
|
||||||
|
}
|
||||||
12
frontend/src/api/generated/model/validationError.ts
Normal file
12
frontend/src/api/generated/model/validationError.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface ValidationError {
|
||||||
|
loc: (string | number)[];
|
||||||
|
msg: string;
|
||||||
|
type: string;
|
||||||
|
}
|
||||||
265
frontend/src/api/generated/org/org.ts
Normal file
265
frontend/src/api/generated/org/org.ts
Normal file
@@ -0,0 +1,265 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
import type {
|
||||||
|
Department,
|
||||||
|
DepartmentCreate,
|
||||||
|
DepartmentUpdate,
|
||||||
|
Employee,
|
||||||
|
EmployeeCreate,
|
||||||
|
EmployeeUpdate,
|
||||||
|
HTTPValidationError,
|
||||||
|
} from ".././model";
|
||||||
|
|
||||||
|
import { customFetch } from "../../mutator";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary List Departments
|
||||||
|
*/
|
||||||
|
export type listDepartmentsDepartmentsGetResponse200 = {
|
||||||
|
data: Department[];
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listDepartmentsDepartmentsGetResponseSuccess =
|
||||||
|
listDepartmentsDepartmentsGetResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type listDepartmentsDepartmentsGetResponse =
|
||||||
|
listDepartmentsDepartmentsGetResponseSuccess;
|
||||||
|
|
||||||
|
export const getListDepartmentsDepartmentsGetUrl = () => {
|
||||||
|
return `/departments`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const listDepartmentsDepartmentsGet = async (
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<listDepartmentsDepartmentsGetResponse> => {
|
||||||
|
return customFetch<listDepartmentsDepartmentsGetResponse>(
|
||||||
|
getListDepartmentsDepartmentsGetUrl(),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Create Department
|
||||||
|
*/
|
||||||
|
export type createDepartmentDepartmentsPostResponse200 = {
|
||||||
|
data: Department;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createDepartmentDepartmentsPostResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createDepartmentDepartmentsPostResponseSuccess =
|
||||||
|
createDepartmentDepartmentsPostResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type createDepartmentDepartmentsPostResponseError =
|
||||||
|
createDepartmentDepartmentsPostResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createDepartmentDepartmentsPostResponse =
|
||||||
|
| createDepartmentDepartmentsPostResponseSuccess
|
||||||
|
| createDepartmentDepartmentsPostResponseError;
|
||||||
|
|
||||||
|
export const getCreateDepartmentDepartmentsPostUrl = () => {
|
||||||
|
return `/departments`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createDepartmentDepartmentsPost = async (
|
||||||
|
departmentCreate: DepartmentCreate,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<createDepartmentDepartmentsPostResponse> => {
|
||||||
|
return customFetch<createDepartmentDepartmentsPostResponse>(
|
||||||
|
getCreateDepartmentDepartmentsPostUrl(),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||||
|
body: JSON.stringify(departmentCreate),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Update Department
|
||||||
|
*/
|
||||||
|
export type updateDepartmentDepartmentsDepartmentIdPatchResponse200 = {
|
||||||
|
data: Department;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateDepartmentDepartmentsDepartmentIdPatchResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateDepartmentDepartmentsDepartmentIdPatchResponseSuccess =
|
||||||
|
updateDepartmentDepartmentsDepartmentIdPatchResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type updateDepartmentDepartmentsDepartmentIdPatchResponseError =
|
||||||
|
updateDepartmentDepartmentsDepartmentIdPatchResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateDepartmentDepartmentsDepartmentIdPatchResponse =
|
||||||
|
| updateDepartmentDepartmentsDepartmentIdPatchResponseSuccess
|
||||||
|
| updateDepartmentDepartmentsDepartmentIdPatchResponseError;
|
||||||
|
|
||||||
|
export const getUpdateDepartmentDepartmentsDepartmentIdPatchUrl = (
|
||||||
|
departmentId: number,
|
||||||
|
) => {
|
||||||
|
return `/departments/${departmentId}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateDepartmentDepartmentsDepartmentIdPatch = async (
|
||||||
|
departmentId: number,
|
||||||
|
departmentUpdate: DepartmentUpdate,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<updateDepartmentDepartmentsDepartmentIdPatchResponse> => {
|
||||||
|
return customFetch<updateDepartmentDepartmentsDepartmentIdPatchResponse>(
|
||||||
|
getUpdateDepartmentDepartmentsDepartmentIdPatchUrl(departmentId),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "PATCH",
|
||||||
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||||
|
body: JSON.stringify(departmentUpdate),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary List Employees
|
||||||
|
*/
|
||||||
|
export type listEmployeesEmployeesGetResponse200 = {
|
||||||
|
data: Employee[];
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listEmployeesEmployeesGetResponseSuccess =
|
||||||
|
listEmployeesEmployeesGetResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type listEmployeesEmployeesGetResponse =
|
||||||
|
listEmployeesEmployeesGetResponseSuccess;
|
||||||
|
|
||||||
|
export const getListEmployeesEmployeesGetUrl = () => {
|
||||||
|
return `/employees`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const listEmployeesEmployeesGet = async (
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<listEmployeesEmployeesGetResponse> => {
|
||||||
|
return customFetch<listEmployeesEmployeesGetResponse>(
|
||||||
|
getListEmployeesEmployeesGetUrl(),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Create Employee
|
||||||
|
*/
|
||||||
|
export type createEmployeeEmployeesPostResponse200 = {
|
||||||
|
data: Employee;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createEmployeeEmployeesPostResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createEmployeeEmployeesPostResponseSuccess =
|
||||||
|
createEmployeeEmployeesPostResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type createEmployeeEmployeesPostResponseError =
|
||||||
|
createEmployeeEmployeesPostResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createEmployeeEmployeesPostResponse =
|
||||||
|
| createEmployeeEmployeesPostResponseSuccess
|
||||||
|
| createEmployeeEmployeesPostResponseError;
|
||||||
|
|
||||||
|
export const getCreateEmployeeEmployeesPostUrl = () => {
|
||||||
|
return `/employees`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createEmployeeEmployeesPost = async (
|
||||||
|
employeeCreate: EmployeeCreate,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<createEmployeeEmployeesPostResponse> => {
|
||||||
|
return customFetch<createEmployeeEmployeesPostResponse>(
|
||||||
|
getCreateEmployeeEmployeesPostUrl(),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||||
|
body: JSON.stringify(employeeCreate),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Update Employee
|
||||||
|
*/
|
||||||
|
export type updateEmployeeEmployeesEmployeeIdPatchResponse200 = {
|
||||||
|
data: Employee;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateEmployeeEmployeesEmployeeIdPatchResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateEmployeeEmployeesEmployeeIdPatchResponseSuccess =
|
||||||
|
updateEmployeeEmployeesEmployeeIdPatchResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type updateEmployeeEmployeesEmployeeIdPatchResponseError =
|
||||||
|
updateEmployeeEmployeesEmployeeIdPatchResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateEmployeeEmployeesEmployeeIdPatchResponse =
|
||||||
|
| updateEmployeeEmployeesEmployeeIdPatchResponseSuccess
|
||||||
|
| updateEmployeeEmployeesEmployeeIdPatchResponseError;
|
||||||
|
|
||||||
|
export const getUpdateEmployeeEmployeesEmployeeIdPatchUrl = (
|
||||||
|
employeeId: number,
|
||||||
|
) => {
|
||||||
|
return `/employees/${employeeId}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateEmployeeEmployeesEmployeeIdPatch = async (
|
||||||
|
employeeId: number,
|
||||||
|
employeeUpdate: EmployeeUpdate,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<updateEmployeeEmployeesEmployeeIdPatchResponse> => {
|
||||||
|
return customFetch<updateEmployeeEmployeesEmployeeIdPatchResponse>(
|
||||||
|
getUpdateEmployeeEmployeesEmployeeIdPatchUrl(employeeId),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "PATCH",
|
||||||
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||||
|
body: JSON.stringify(employeeUpdate),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
138
frontend/src/api/generated/projects/projects.ts
Normal file
138
frontend/src/api/generated/projects/projects.ts
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
import type {
|
||||||
|
HTTPValidationError,
|
||||||
|
Project,
|
||||||
|
ProjectCreate,
|
||||||
|
ProjectUpdate,
|
||||||
|
} from ".././model";
|
||||||
|
|
||||||
|
import { customFetch } from "../../mutator";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary List Projects
|
||||||
|
*/
|
||||||
|
export type listProjectsProjectsGetResponse200 = {
|
||||||
|
data: Project[];
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listProjectsProjectsGetResponseSuccess =
|
||||||
|
listProjectsProjectsGetResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type listProjectsProjectsGetResponse =
|
||||||
|
listProjectsProjectsGetResponseSuccess;
|
||||||
|
|
||||||
|
export const getListProjectsProjectsGetUrl = () => {
|
||||||
|
return `/projects`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const listProjectsProjectsGet = async (
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<listProjectsProjectsGetResponse> => {
|
||||||
|
return customFetch<listProjectsProjectsGetResponse>(
|
||||||
|
getListProjectsProjectsGetUrl(),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Create Project
|
||||||
|
*/
|
||||||
|
export type createProjectProjectsPostResponse200 = {
|
||||||
|
data: Project;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createProjectProjectsPostResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createProjectProjectsPostResponseSuccess =
|
||||||
|
createProjectProjectsPostResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type createProjectProjectsPostResponseError =
|
||||||
|
createProjectProjectsPostResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createProjectProjectsPostResponse =
|
||||||
|
| createProjectProjectsPostResponseSuccess
|
||||||
|
| createProjectProjectsPostResponseError;
|
||||||
|
|
||||||
|
export const getCreateProjectProjectsPostUrl = () => {
|
||||||
|
return `/projects`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createProjectProjectsPost = async (
|
||||||
|
projectCreate: ProjectCreate,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<createProjectProjectsPostResponse> => {
|
||||||
|
return customFetch<createProjectProjectsPostResponse>(
|
||||||
|
getCreateProjectProjectsPostUrl(),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||||
|
body: JSON.stringify(projectCreate),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Update Project
|
||||||
|
*/
|
||||||
|
export type updateProjectProjectsProjectIdPatchResponse200 = {
|
||||||
|
data: Project;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateProjectProjectsProjectIdPatchResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateProjectProjectsProjectIdPatchResponseSuccess =
|
||||||
|
updateProjectProjectsProjectIdPatchResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type updateProjectProjectsProjectIdPatchResponseError =
|
||||||
|
updateProjectProjectsProjectIdPatchResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateProjectProjectsProjectIdPatchResponse =
|
||||||
|
| updateProjectProjectsProjectIdPatchResponseSuccess
|
||||||
|
| updateProjectProjectsProjectIdPatchResponseError;
|
||||||
|
|
||||||
|
export const getUpdateProjectProjectsProjectIdPatchUrl = (
|
||||||
|
projectId: number,
|
||||||
|
) => {
|
||||||
|
return `/projects/${projectId}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateProjectProjectsProjectIdPatch = async (
|
||||||
|
projectId: number,
|
||||||
|
projectUpdate: ProjectUpdate,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<updateProjectProjectsProjectIdPatchResponse> => {
|
||||||
|
return customFetch<updateProjectProjectsProjectIdPatchResponse>(
|
||||||
|
getUpdateProjectProjectsProjectIdPatchUrl(projectId),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "PATCH",
|
||||||
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||||
|
body: JSON.stringify(projectUpdate),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
304
frontend/src/api/generated/work/work.ts
Normal file
304
frontend/src/api/generated/work/work.ts
Normal file
@@ -0,0 +1,304 @@
|
|||||||
|
/**
|
||||||
|
* Generated by orval v8.2.0 🍺
|
||||||
|
* Do not edit manually.
|
||||||
|
* OpenClaw Agency API
|
||||||
|
* OpenAPI spec version: 0.3.0
|
||||||
|
*/
|
||||||
|
import type {
|
||||||
|
HTTPValidationError,
|
||||||
|
ListTaskCommentsTaskCommentsGetParams,
|
||||||
|
ListTasksTasksGetParams,
|
||||||
|
Task,
|
||||||
|
TaskComment,
|
||||||
|
TaskCommentCreate,
|
||||||
|
TaskCreate,
|
||||||
|
TaskUpdate,
|
||||||
|
} from ".././model";
|
||||||
|
|
||||||
|
import { customFetch } from "../../mutator";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary List Tasks
|
||||||
|
*/
|
||||||
|
export type listTasksTasksGetResponse200 = {
|
||||||
|
data: Task[];
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listTasksTasksGetResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listTasksTasksGetResponseSuccess = listTasksTasksGetResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type listTasksTasksGetResponseError = listTasksTasksGetResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listTasksTasksGetResponse =
|
||||||
|
| listTasksTasksGetResponseSuccess
|
||||||
|
| listTasksTasksGetResponseError;
|
||||||
|
|
||||||
|
export const getListTasksTasksGetUrl = (params?: ListTasksTasksGetParams) => {
|
||||||
|
const normalizedParams = new URLSearchParams();
|
||||||
|
|
||||||
|
Object.entries(params || {}).forEach(([key, value]) => {
|
||||||
|
if (value !== undefined) {
|
||||||
|
normalizedParams.append(key, value === null ? "null" : value.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const stringifiedParams = normalizedParams.toString();
|
||||||
|
|
||||||
|
return stringifiedParams.length > 0
|
||||||
|
? `/tasks?${stringifiedParams}`
|
||||||
|
: `/tasks`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const listTasksTasksGet = async (
|
||||||
|
params?: ListTasksTasksGetParams,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<listTasksTasksGetResponse> => {
|
||||||
|
return customFetch<listTasksTasksGetResponse>(
|
||||||
|
getListTasksTasksGetUrl(params),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Create Task
|
||||||
|
*/
|
||||||
|
export type createTaskTasksPostResponse200 = {
|
||||||
|
data: Task;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createTaskTasksPostResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createTaskTasksPostResponseSuccess =
|
||||||
|
createTaskTasksPostResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type createTaskTasksPostResponseError =
|
||||||
|
createTaskTasksPostResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createTaskTasksPostResponse =
|
||||||
|
| createTaskTasksPostResponseSuccess
|
||||||
|
| createTaskTasksPostResponseError;
|
||||||
|
|
||||||
|
export const getCreateTaskTasksPostUrl = () => {
|
||||||
|
return `/tasks`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createTaskTasksPost = async (
|
||||||
|
taskCreate: TaskCreate,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<createTaskTasksPostResponse> => {
|
||||||
|
return customFetch<createTaskTasksPostResponse>(getCreateTaskTasksPostUrl(), {
|
||||||
|
...options,
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||||
|
body: JSON.stringify(taskCreate),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Update Task
|
||||||
|
*/
|
||||||
|
export type updateTaskTasksTaskIdPatchResponse200 = {
|
||||||
|
data: Task;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateTaskTasksTaskIdPatchResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateTaskTasksTaskIdPatchResponseSuccess =
|
||||||
|
updateTaskTasksTaskIdPatchResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type updateTaskTasksTaskIdPatchResponseError =
|
||||||
|
updateTaskTasksTaskIdPatchResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type updateTaskTasksTaskIdPatchResponse =
|
||||||
|
| updateTaskTasksTaskIdPatchResponseSuccess
|
||||||
|
| updateTaskTasksTaskIdPatchResponseError;
|
||||||
|
|
||||||
|
export const getUpdateTaskTasksTaskIdPatchUrl = (taskId: number) => {
|
||||||
|
return `/tasks/${taskId}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const updateTaskTasksTaskIdPatch = async (
|
||||||
|
taskId: number,
|
||||||
|
taskUpdate: TaskUpdate,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<updateTaskTasksTaskIdPatchResponse> => {
|
||||||
|
return customFetch<updateTaskTasksTaskIdPatchResponse>(
|
||||||
|
getUpdateTaskTasksTaskIdPatchUrl(taskId),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "PATCH",
|
||||||
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||||
|
body: JSON.stringify(taskUpdate),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Delete Task
|
||||||
|
*/
|
||||||
|
export type deleteTaskTasksTaskIdDeleteResponse200 = {
|
||||||
|
data: unknown;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type deleteTaskTasksTaskIdDeleteResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type deleteTaskTasksTaskIdDeleteResponseSuccess =
|
||||||
|
deleteTaskTasksTaskIdDeleteResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type deleteTaskTasksTaskIdDeleteResponseError =
|
||||||
|
deleteTaskTasksTaskIdDeleteResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type deleteTaskTasksTaskIdDeleteResponse =
|
||||||
|
| deleteTaskTasksTaskIdDeleteResponseSuccess
|
||||||
|
| deleteTaskTasksTaskIdDeleteResponseError;
|
||||||
|
|
||||||
|
export const getDeleteTaskTasksTaskIdDeleteUrl = (taskId: number) => {
|
||||||
|
return `/tasks/${taskId}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const deleteTaskTasksTaskIdDelete = async (
|
||||||
|
taskId: number,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<deleteTaskTasksTaskIdDeleteResponse> => {
|
||||||
|
return customFetch<deleteTaskTasksTaskIdDeleteResponse>(
|
||||||
|
getDeleteTaskTasksTaskIdDeleteUrl(taskId),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "DELETE",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary List Task Comments
|
||||||
|
*/
|
||||||
|
export type listTaskCommentsTaskCommentsGetResponse200 = {
|
||||||
|
data: TaskComment[];
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listTaskCommentsTaskCommentsGetResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listTaskCommentsTaskCommentsGetResponseSuccess =
|
||||||
|
listTaskCommentsTaskCommentsGetResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type listTaskCommentsTaskCommentsGetResponseError =
|
||||||
|
listTaskCommentsTaskCommentsGetResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type listTaskCommentsTaskCommentsGetResponse =
|
||||||
|
| listTaskCommentsTaskCommentsGetResponseSuccess
|
||||||
|
| listTaskCommentsTaskCommentsGetResponseError;
|
||||||
|
|
||||||
|
export const getListTaskCommentsTaskCommentsGetUrl = (
|
||||||
|
params: ListTaskCommentsTaskCommentsGetParams,
|
||||||
|
) => {
|
||||||
|
const normalizedParams = new URLSearchParams();
|
||||||
|
|
||||||
|
Object.entries(params || {}).forEach(([key, value]) => {
|
||||||
|
if (value !== undefined) {
|
||||||
|
normalizedParams.append(key, value === null ? "null" : value.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const stringifiedParams = normalizedParams.toString();
|
||||||
|
|
||||||
|
return stringifiedParams.length > 0
|
||||||
|
? `/task-comments?${stringifiedParams}`
|
||||||
|
: `/task-comments`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const listTaskCommentsTaskCommentsGet = async (
|
||||||
|
params: ListTaskCommentsTaskCommentsGetParams,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<listTaskCommentsTaskCommentsGetResponse> => {
|
||||||
|
return customFetch<listTaskCommentsTaskCommentsGetResponse>(
|
||||||
|
getListTaskCommentsTaskCommentsGetUrl(params),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "GET",
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @summary Create Task Comment
|
||||||
|
*/
|
||||||
|
export type createTaskCommentTaskCommentsPostResponse200 = {
|
||||||
|
data: TaskComment;
|
||||||
|
status: 200;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createTaskCommentTaskCommentsPostResponse422 = {
|
||||||
|
data: HTTPValidationError;
|
||||||
|
status: 422;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createTaskCommentTaskCommentsPostResponseSuccess =
|
||||||
|
createTaskCommentTaskCommentsPostResponse200 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
export type createTaskCommentTaskCommentsPostResponseError =
|
||||||
|
createTaskCommentTaskCommentsPostResponse422 & {
|
||||||
|
headers: Headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type createTaskCommentTaskCommentsPostResponse =
|
||||||
|
| createTaskCommentTaskCommentsPostResponseSuccess
|
||||||
|
| createTaskCommentTaskCommentsPostResponseError;
|
||||||
|
|
||||||
|
export const getCreateTaskCommentTaskCommentsPostUrl = () => {
|
||||||
|
return `/task-comments`;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createTaskCommentTaskCommentsPost = async (
|
||||||
|
taskCommentCreate: TaskCommentCreate,
|
||||||
|
options?: RequestInit,
|
||||||
|
): Promise<createTaskCommentTaskCommentsPostResponse> => {
|
||||||
|
return customFetch<createTaskCommentTaskCommentsPostResponse>(
|
||||||
|
getCreateTaskCommentTaskCommentsPostUrl(),
|
||||||
|
{
|
||||||
|
...options,
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json", ...options?.headers },
|
||||||
|
body: JSON.stringify(taskCommentCreate),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
};
|
||||||
22
frontend/src/api/mutator.ts
Normal file
22
frontend/src/api/mutator.ts
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
export async function customFetch<T>(
|
||||||
|
url: string,
|
||||||
|
options: RequestInit,
|
||||||
|
): Promise<T> {
|
||||||
|
const base = process.env.NEXT_PUBLIC_API_URL;
|
||||||
|
if (!base) throw new Error("NEXT_PUBLIC_API_URL is not set");
|
||||||
|
|
||||||
|
const res = await fetch(`${base}${url}`, {
|
||||||
|
...options,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
...(options.headers ?? {}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
const text = await res.text().catch(() => "");
|
||||||
|
throw new Error(`${res.status} ${res.statusText}${text ? `: ${text}` : ""}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (await res.json()) as T;
|
||||||
|
}
|
||||||
@@ -1,13 +1,67 @@
|
|||||||
:root{
|
@tailwind base;
|
||||||
--mc-bg:#f6f4ef;
|
@tailwind components;
|
||||||
--mc-surface:#ffffff;
|
@tailwind utilities;
|
||||||
--mc-border:rgba(15,23,42,0.10);
|
|
||||||
--mc-text:#0f172a;
|
:root {
|
||||||
--mc-muted:rgba(15,23,42,0.62);
|
--background: 0 0% 100%;
|
||||||
--mc-accent:#2563eb;
|
--foreground: 222.2 84% 4.9%;
|
||||||
--mc-font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
|
|
||||||
--mc-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--muted: 210 40% 96.1%;
|
||||||
|
--muted-foreground: 215.4 16.3% 46.9%;
|
||||||
|
|
||||||
|
--accent: 210 40% 96.1%;
|
||||||
|
--accent-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--border: 214.3 31.8% 91.4%;
|
||||||
|
--input: 214.3 31.8% 91.4%;
|
||||||
|
--ring: 222.2 84% 4.9%;
|
||||||
|
|
||||||
|
--primary: 222.2 47.4% 11.2%;
|
||||||
|
--primary-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--secondary: 210 40% 96.1%;
|
||||||
|
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--destructive: 0 84.2% 60.2%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--radius: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--background: 222.2 84% 4.9%;
|
||||||
|
--foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--card: 222.2 84% 4.9%;
|
||||||
|
--card-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--muted: 217.2 32.6% 17.5%;
|
||||||
|
--muted-foreground: 215 20.2% 65.1%;
|
||||||
|
|
||||||
|
--accent: 217.2 32.6% 17.5%;
|
||||||
|
--accent-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--border: 217.2 32.6% 17.5%;
|
||||||
|
--input: 217.2 32.6% 17.5%;
|
||||||
|
--ring: 212.7 26.8% 83.9%;
|
||||||
|
|
||||||
|
--primary: 210 40% 98%;
|
||||||
|
--primary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--secondary: 217.2 32.6% 17.5%;
|
||||||
|
--secondary-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--destructive: 0 62.8% 30.6%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
@apply border-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
@apply bg-background text-foreground;
|
||||||
}
|
}
|
||||||
html,body{height:100%}
|
|
||||||
body{margin:0;color:var(--mc-text);background:var(--mc-bg);font-family: ui-sans-serif, system-ui, -apple-system, Segoe UI, Roboto, Helvetica, Arial, "Apple Color Emoji","Segoe UI Emoji";}
|
|
||||||
*{box-sizing:border-box}
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
import { Providers } from "./providers";
|
||||||
import { Shell } from "./_components/Shell";
|
import { Shell } from "./_components/Shell";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
@@ -15,7 +16,7 @@ export default function RootLayout({
|
|||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<body>
|
<body>
|
||||||
<Shell>{children}</Shell>
|
<Shell><Providers>{children}</Providers></Shell>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,146 +1,68 @@
|
|||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import { useEffect, useState } from "react";
|
import { Button } from "@/components/ui/button";
|
||||||
import styles from "./_components/Shell.module.css";
|
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { apiGet } from "../lib/api";
|
|
||||||
|
|
||||||
type Activity = {
|
import { useListProjectsProjectsGet } from "@/api/generated/projects/projects";
|
||||||
id: number;
|
|
||||||
actor_employee_id: number | null;
|
|
||||||
entity_type: string;
|
|
||||||
entity_id: number | null;
|
|
||||||
verb: string;
|
|
||||||
payload: any;
|
|
||||||
created_at: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Project = { id: number; name: string; status: string };
|
export default function Home() {
|
||||||
|
const projects = useListProjectsProjectsGet();
|
||||||
type Department = { id: number; name: string; head_employee_id: number | null };
|
|
||||||
|
|
||||||
type Employee = {
|
|
||||||
id: number;
|
|
||||||
name: string;
|
|
||||||
employee_type: string;
|
|
||||||
department_id: number | null;
|
|
||||||
manager_id: number | null;
|
|
||||||
title: string | null;
|
|
||||||
status: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type Task = {
|
|
||||||
id: number;
|
|
||||||
project_id: number;
|
|
||||||
title: string;
|
|
||||||
status: string;
|
|
||||||
assignee_employee_id: number | null;
|
|
||||||
reviewer_employee_id: number | null;
|
|
||||||
created_at: string;
|
|
||||||
updated_at: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export default function MissionControlHome() {
|
|
||||||
const [activities, setActivities] = useState<Activity[]>([]);
|
|
||||||
const [projects, setProjects] = useState<Project[]>([]);
|
|
||||||
const [departments, setDepartments] = useState<Department[]>([]);
|
|
||||||
const [employees, setEmployees] = useState<Employee[]>([]);
|
|
||||||
const [tasks, setTasks] = useState<Task[]>([]);
|
|
||||||
const [error, setError] = useState<string | null>(null);
|
|
||||||
|
|
||||||
async function load() {
|
|
||||||
setError(null);
|
|
||||||
try {
|
|
||||||
const [a, p, d, e, t] = await Promise.all([
|
|
||||||
apiGet<Activity[]>("/activities?limit=20"),
|
|
||||||
apiGet<Project[]>("/projects"),
|
|
||||||
apiGet<Department[]>("/departments"),
|
|
||||||
apiGet<Employee[]>("/employees"),
|
|
||||||
apiGet<Task[]>("/tasks"),
|
|
||||||
]);
|
|
||||||
setActivities(a);
|
|
||||||
setProjects(p);
|
|
||||||
setDepartments(d);
|
|
||||||
setEmployees(e);
|
|
||||||
setTasks(t);
|
|
||||||
} catch (err: unknown) {
|
|
||||||
setError(err instanceof Error ? err.message : "Unknown error");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
load();
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const activeProjects = projects.filter((x) => x.status === "active").length;
|
|
||||||
const activeEmployees = employees.filter((x) => x.status === "active").length;
|
|
||||||
const blockedTasks = tasks.filter((t) => t.status === "blocked").length;
|
|
||||||
const reviewQueue = tasks.filter((t) => t.status === "review").length;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<main>
|
<main className="mx-auto max-w-5xl p-6">
|
||||||
<div className={styles.topbar}>
|
<div className="flex items-start justify-between gap-4">
|
||||||
<div>
|
<div>
|
||||||
<h1 className={styles.h1}>Mission Control</h1>
|
<h1 className="text-3xl font-semibold tracking-tight">Company Mission Control</h1>
|
||||||
<p className={styles.p}>
|
<p className="mt-2 text-sm text-muted-foreground">
|
||||||
Company dashboard: departments, employees/agents, projects, and work — designed to run like a real org.
|
Orval-generated client + React Query + shadcn-style components.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<button className={styles.btn} onClick={load}>
|
<Button variant="outline" onClick={() => projects.refetch()} disabled={projects.isFetching}>
|
||||||
Refresh
|
Refresh
|
||||||
</button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{error ? (
|
<div className="mt-6 grid gap-4 sm:grid-cols-2">
|
||||||
<div className={styles.card} style={{ borderColor: "rgba(176,0,32,0.25)" }}>
|
<Card>
|
||||||
<div className={styles.cardTitle}>Error</div>
|
<CardHeader>
|
||||||
<div style={{ color: "#b00020" }}>{error}</div>
|
<CardTitle>Projects</CardTitle>
|
||||||
</div>
|
<CardDescription>GET /projects</CardDescription>
|
||||||
) : null}
|
</CardHeader>
|
||||||
|
<CardContent>
|
||||||
|
{projects.isLoading ? <div className="text-sm text-muted-foreground">Loading…</div> : null}
|
||||||
|
{projects.error ? (
|
||||||
|
<div className="text-sm text-destructive">{(projects.error as Error).message}</div>
|
||||||
|
) : null}
|
||||||
|
{!projects.isLoading && !projects.error ? (
|
||||||
|
<ul className="space-y-2">
|
||||||
|
{projects.data?.map((p) => (
|
||||||
|
<li key={p.id ?? p.name} className="flex items-center justify-between rounded-md border p-3">
|
||||||
|
<div className="font-medium">{p.name}</div>
|
||||||
|
<div className="text-xs text-muted-foreground">{p.status}</div>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
{(projects.data?.length ?? 0) === 0 ? (
|
||||||
|
<li className="text-sm text-muted-foreground">No projects yet.</li>
|
||||||
|
) : null}
|
||||||
|
</ul>
|
||||||
|
) : null}
|
||||||
|
</CardContent>
|
||||||
|
</Card>
|
||||||
|
|
||||||
<div className={styles.grid2} style={{ marginTop: 16 }}>
|
<Card>
|
||||||
<section className={styles.card}>
|
<CardHeader>
|
||||||
<div className={styles.cardTitle}>Company Snapshot</div>
|
<CardTitle>API</CardTitle>
|
||||||
<div style={{ display: "flex", gap: 10, flexWrap: "wrap" }}>
|
<CardDescription>Docs & health</CardDescription>
|
||||||
<span className={styles.badge}>Projects: {activeProjects}</span>
|
</CardHeader>
|
||||||
<span className={styles.badge}>Departments: {departments.length}</span>
|
<CardContent className="space-y-2 text-sm">
|
||||||
<span className={styles.badge}>Active people: {activeEmployees}</span>
|
<div>
|
||||||
<span className={styles.badge}>In review: {reviewQueue}</span>
|
<span className="text-muted-foreground">Docs:</span> <code className="ml-2">/docs</code>
|
||||||
<span className={styles.badge}>Blocked: {blockedTasks}</span>
|
</div>
|
||||||
</div>
|
<div className="text-muted-foreground">
|
||||||
<div className={styles.list} style={{ marginTop: 12 }}>
|
Set <code>NEXT_PUBLIC_API_URL</code> in <code>.env.local</code> (example: http://192.168.1.101:8000).
|
||||||
{projects.slice(0, 6).map((p) => (
|
</div>
|
||||||
<div key={p.id} className={styles.item}>
|
</CardContent>
|
||||||
<div style={{ display: "flex", justifyContent: "space-between", gap: 12 }}>
|
</Card>
|
||||||
<div style={{ fontWeight: 650 }}>{p.name}</div>
|
|
||||||
<span className={styles.badge}>{p.status}</span>
|
|
||||||
</div>
|
|
||||||
<div className={styles.mono} style={{ marginTop: 6 }}>
|
|
||||||
Project ID: {p.id}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
{projects.length === 0 ? <div className={styles.mono}>No projects yet. Create one in Projects.</div> : null}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section className={styles.card}>
|
|
||||||
<div className={styles.cardTitle}>Activity Feed</div>
|
|
||||||
<div className={styles.list}>
|
|
||||||
{activities.map((a) => (
|
|
||||||
<div key={a.id} className={styles.item}>
|
|
||||||
<div style={{ display: "flex", justifyContent: "space-between", gap: 12 }}>
|
|
||||||
<div>
|
|
||||||
<span style={{ fontWeight: 650 }}>{a.entity_type}</span> · {a.verb}
|
|
||||||
{a.entity_id != null ? ` #${a.entity_id}` : ""}
|
|
||||||
</div>
|
|
||||||
<span className={styles.mono}>{new Date(a.created_at).toLocaleString()}</span>
|
|
||||||
</div>
|
|
||||||
{a.payload ? <div className={styles.mono} style={{ marginTop: 6 }}>{JSON.stringify(a.payload)}</div> : null}
|
|
||||||
</div>
|
|
||||||
))}
|
|
||||||
{activities.length === 0 ? <div className={styles.mono}>No activity yet.</div> : null}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
);
|
);
|
||||||
|
|||||||
20
frontend/src/app/providers.tsx
Normal file
20
frontend/src/app/providers.tsx
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
||||||
|
import { useState } from "react";
|
||||||
|
|
||||||
|
export function Providers({ children }: { children: React.ReactNode }) {
|
||||||
|
const [client] = useState(
|
||||||
|
() =>
|
||||||
|
new QueryClient({
|
||||||
|
defaultOptions: {
|
||||||
|
queries: {
|
||||||
|
retry: 1,
|
||||||
|
refetchOnWindowFocus: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return <QueryClientProvider client={client}>{children}</QueryClientProvider>;
|
||||||
|
}
|
||||||
49
frontend/src/components/ui/button.tsx
Normal file
49
frontend/src/components/ui/button.tsx
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import { cva, type VariantProps } from "class-variance-authority";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const buttonVariants = cva(
|
||||||
|
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50",
|
||||||
|
{
|
||||||
|
variants: {
|
||||||
|
variant: {
|
||||||
|
default: "bg-primary text-primary-foreground hover:opacity-90",
|
||||||
|
secondary: "bg-secondary text-secondary-foreground hover:opacity-90",
|
||||||
|
outline: "border border-input bg-background hover:bg-accent hover:text-accent-foreground",
|
||||||
|
destructive: "bg-destructive text-destructive-foreground hover:opacity-90",
|
||||||
|
ghost: "hover:bg-accent hover:text-accent-foreground",
|
||||||
|
link: "text-primary underline-offset-4 hover:underline",
|
||||||
|
},
|
||||||
|
size: {
|
||||||
|
default: "h-10 px-4 py-2",
|
||||||
|
sm: "h-9 rounded-md px-3",
|
||||||
|
lg: "h-11 rounded-md px-8",
|
||||||
|
icon: "h-10 w-10",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
variant: "default",
|
||||||
|
size: "default",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export interface ButtonProps
|
||||||
|
extends React.ButtonHTMLAttributes<HTMLButtonElement>,
|
||||||
|
VariantProps<typeof buttonVariants> {}
|
||||||
|
|
||||||
|
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
||||||
|
({ className, variant, size, ...props }, ref) => {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
className={cn(buttonVariants({ variant, size, className }))}
|
||||||
|
ref={ref}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
Button.displayName = "Button";
|
||||||
|
|
||||||
|
export { Button, buttonVariants };
|
||||||
51
frontend/src/components/ui/card.tsx
Normal file
51
frontend/src/components/ui/card.tsx
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
|
||||||
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
|
const Card = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
||||||
|
({ className, ...props }, ref) => (
|
||||||
|
<div
|
||||||
|
ref={ref}
|
||||||
|
className={cn("rounded-lg border bg-card text-card-foreground shadow-sm", className)}
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
);
|
||||||
|
Card.displayName = "Card";
|
||||||
|
|
||||||
|
const CardHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
||||||
|
({ className, ...props }, ref) => (
|
||||||
|
<div ref={ref} className={cn("flex flex-col space-y-1.5 p-6", className)} {...props} />
|
||||||
|
)
|
||||||
|
);
|
||||||
|
CardHeader.displayName = "CardHeader";
|
||||||
|
|
||||||
|
const CardTitle = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLHeadingElement>>(
|
||||||
|
({ className, ...props }, ref) => (
|
||||||
|
<h3 ref={ref} className={cn("text-2xl font-semibold leading-none tracking-tight", className)} {...props} />
|
||||||
|
)
|
||||||
|
);
|
||||||
|
CardTitle.displayName = "CardTitle";
|
||||||
|
|
||||||
|
const CardDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
|
||||||
|
({ className, ...props }, ref) => (
|
||||||
|
<p ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
|
||||||
|
)
|
||||||
|
);
|
||||||
|
CardDescription.displayName = "CardDescription";
|
||||||
|
|
||||||
|
const CardContent = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
||||||
|
({ className, ...props }, ref) => (
|
||||||
|
<div ref={ref} className={cn("p-6 pt-0", className)} {...props} />
|
||||||
|
)
|
||||||
|
);
|
||||||
|
CardContent.displayName = "CardContent";
|
||||||
|
|
||||||
|
const CardFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
||||||
|
({ className, ...props }, ref) => (
|
||||||
|
<div ref={ref} className={cn("flex items-center p-6 pt-0", className)} {...props} />
|
||||||
|
)
|
||||||
|
);
|
||||||
|
CardFooter.displayName = "CardFooter";
|
||||||
|
|
||||||
|
export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
|
||||||
6
frontend/src/lib/utils.ts
Normal file
6
frontend/src/lib/utils.ts
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
import { clsx, type ClassValue } from "clsx";
|
||||||
|
import { twMerge } from "tailwind-merge";
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs));
|
||||||
|
}
|
||||||
50
frontend/tailwind.config.cjs
Normal file
50
frontend/tailwind.config.cjs
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
darkMode: ["class"],
|
||||||
|
content: [
|
||||||
|
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
extend: {
|
||||||
|
borderRadius: {
|
||||||
|
lg: "var(--radius)",
|
||||||
|
md: "calc(var(--radius) - 2px)",
|
||||||
|
sm: "calc(var(--radius) - 4px)",
|
||||||
|
},
|
||||||
|
colors: {
|
||||||
|
border: "hsl(var(--border))",
|
||||||
|
input: "hsl(var(--input))",
|
||||||
|
ring: "hsl(var(--ring))",
|
||||||
|
background: "hsl(var(--background))",
|
||||||
|
foreground: "hsl(var(--foreground))",
|
||||||
|
primary: {
|
||||||
|
DEFAULT: "hsl(var(--primary))",
|
||||||
|
foreground: "hsl(var(--primary-foreground))",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: "hsl(var(--secondary))",
|
||||||
|
foreground: "hsl(var(--secondary-foreground))",
|
||||||
|
},
|
||||||
|
muted: {
|
||||||
|
DEFAULT: "hsl(var(--muted))",
|
||||||
|
foreground: "hsl(var(--muted-foreground))",
|
||||||
|
},
|
||||||
|
accent: {
|
||||||
|
DEFAULT: "hsl(var(--accent))",
|
||||||
|
foreground: "hsl(var(--accent-foreground))",
|
||||||
|
},
|
||||||
|
destructive: {
|
||||||
|
DEFAULT: "hsl(var(--destructive))",
|
||||||
|
foreground: "hsl(var(--destructive-foreground))",
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
DEFAULT: "hsl(var(--card))",
|
||||||
|
foreground: "hsl(var(--card-foreground))",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [require("tailwindcss-animate")],
|
||||||
|
};
|
||||||
@@ -11,24 +11,13 @@
|
|||||||
"moduleResolution": "bundler",
|
"moduleResolution": "bundler",
|
||||||
"resolveJsonModule": true,
|
"resolveJsonModule": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"jsx": "react-jsx",
|
"jsx": "preserve",
|
||||||
"incremental": true,
|
"incremental": true,
|
||||||
"plugins": [
|
"plugins": [{ "name": "next" }],
|
||||||
{
|
|
||||||
"name": "next"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"paths": {
|
"paths": {
|
||||||
"@/*": ["./src/*"]
|
"@/*": ["./src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
"next-env.d.ts",
|
|
||||||
"**/*.ts",
|
|
||||||
"**/*.tsx",
|
|
||||||
".next/types/**/*.ts",
|
|
||||||
".next/dev/types/**/*.ts",
|
|
||||||
"**/*.mts"
|
|
||||||
],
|
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user