Skip to content

Commit

Permalink
Create troi time entries via server
Browse files Browse the repository at this point in the history
  • Loading branch information
malte-laukoetter committed Dec 15, 2023
1 parent 9072c5e commit fef4160
Show file tree
Hide file tree
Showing 3 changed files with 136 additions and 35 deletions.
33 changes: 17 additions & 16 deletions app/components/troi.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import {
import moment from "moment";
import { TimeEntries, TimeEntry } from "~/troi/TimeEntry";
import { CalculationPosition } from "~/troi/CalculationPosition";
import { useFetcher } from "@remix-run/react";
import { convertToCacheFormat } from "~/utils/TimeEntryCache";

interface Props {
username: string;
Expand Down Expand Up @@ -71,21 +73,25 @@ export default function Troi(props: Props) {
selectedDate,
);

const fetcher = useFetcher();

async function onAddEntryClicked(
position: CalculationPosition,
hours: number,
description: string,
) {
// await troiController?.addEntry(
// selectedDate,
// position,
// hours,
// description,
// () => {}
// );
// troiController?.getEntriesFor(selectedDate).then((entries) => {
// setEntriesForSelectedDate(entries);
// });
fetcher.submit(
{
hours,
description,
},
{
method: "POST",
action: `/calculation_postions/${
position.id
}/time_entries/${convertToCacheFormat(selectedDate)}`,
},
);
}

async function onUpdateEntryClicked(
Expand All @@ -98,12 +104,7 @@ export default function Troi(props: Props) {
// });
}

async function onDeleteEntryClicked(entry: TimeEntry, positionId: number) {
// await troiController?.deleteEntry(entry, positionId, () => {});
// troiController?.getEntriesFor(selectedDate).then((entries) => {
// setEntriesForSelectedDate(entries);
// });
}
async function onDeleteEntryClicked(entry: TimeEntry, positionId: number) {}

return (
<div>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { ActionFunctionArgs } from "@remix-run/node";
import TroiApiService from "troi-library";
import { login } from "~/cookies.server";
import { addTimeEntry } from "~/troi/troiControllerServer";

export async function action({ request, params }: ActionFunctionArgs) {
if (request.method !== "POST") {
throw new Error("MethodNotAllowed");
// todo (Malte Laukötter, 2023-12-15): throw a error with the correct error type (405)
}

if (params.calculationPositionId === undefined) {
throw new Error("Missing calculationPositionId");
}

if (params.date === undefined) {
throw new Error("Missing date");
}

const body = await request.formData();

const hours = body.get("hours");
if (typeof hours !== "string") {
throw new Error("Missing hours");
}

const description = body.get("description");
if (typeof description !== "string") {
throw new Error("Missing description");
}

addTimeEntry(
request,
parseInt(params.calculationPositionId, 10),
params.date,
parseFloat(hours),
description,
);

return;
}
97 changes: 78 additions & 19 deletions app/troi/troiControllerServer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,14 @@ async function fetchCalculationPositionsAndSaveToSession(request: Request) {
clientId: clientId.toString(),
favoritesOnly: true.toString(),
},
})) as any[]
).map((obj: any) => ({
})) as {
Id: number;
DisplayPath: string;
Subproject: {
id: number;
};
}[]
).map((obj) => ({
name: obj.DisplayPath,
id: obj.Id,
subprojectId: obj.Subproject.id,
Expand Down Expand Up @@ -169,28 +175,37 @@ async function fetchTimeEntriesAndSaveToSession(request: Request) {
const calculationPositions = await getCalculationPositions(request);
const entries: TimeEntry[] = (
await Promise.all(
calculationPositions.map((calcPos) =>
troiApi.makeRequest({
url: "/billings/hours",
params: {
clientId: clientId.toString(),
employeeId: employeeId.toString(),
calculationPositionId: calcPos.id.toString(),
startDate: formatDateToYYYYMMDD(addDaysToDate(new Date(), -366)),
endDate: formatDateToYYYYMMDD(addDaysToDate(new Date(), 366)),
},
}),
calculationPositions.map(
(calcPos) =>
troiApi.makeRequest({
url: "/billings/hours",
params: {
clientId: clientId.toString(),
employeeId: employeeId.toString(),
calculationPositionId: calcPos.id.toString(),
startDate: formatDateToYYYYMMDD(addDaysToDate(new Date(), -366)),
endDate: formatDateToYYYYMMDD(addDaysToDate(new Date(), 366)),
},
}) as Promise<{
id: number;
Date: string;
Quantity: string;
Remark: string;
CalculationPosition: {
id: number;
};
}>,
),
)
)
.flat()
.map((e: any) => {
.map((entry) => {
return {
id: e.id,
date: e.Date,
hours: e.Quantity,
description: e.Remark,
calculationPosition: e.CalculationPosition.id,
id: entry.id,
date: entry.Date,
hours: parseFloat(entry.Quantity),
description: entry.Remark,
calculationPosition: entry.CalculationPosition.id,
};
});

Expand All @@ -213,6 +228,50 @@ export async function getTimeEntries(request: Request): Promise<TimeEntries> {
);
}

export async function addTimeEntry(
request: Request,
calculationPostionId: number,
date: string,
hours: number,
description: string,
) {
const cookieHeader = request.headers.get("Cookie");
const session = await getSession(cookieHeader);

const troiApi = await getTroiApi(
session.get("username"),
session.get("troiPassword"),
await getClientId(request),
await getEmployeeId(request),
);

const result = (await troiApi.postTimeEntry(
calculationPostionId,
date,
hours,
description,
)) as {
id: number;
Name: string;
Quantity: string;
};

const existingEntries = session.get("troiTimeEntries");
if (existingEntries !== undefined) {
existingEntries[result.id] = {
id: result.id,
date: date,
hours: parseFloat(result.Quantity),
description: result.Name,
calculationPosition: calculationPostionId,
};
}

await commitSession(session);

return result;
}

/**
* Return data from the session cache and revalidate cached data in the background.
*
Expand Down

0 comments on commit fef4160

Please sign in to comment.