Pārlūkot izejas kodu

Merge branch 'main' of https://git.2fi-solutions.com/wayne.lee/tsms

tags/Baseline_30082024_FRONTEND_UAT
MSI\2Fi pirms 1 gada
vecāks
revīzija
2060b168d2
7 mainītis faili ar 208 papildinājumiem un 13 dzēšanām
  1. +18
    -1
      src/components/CreateProject/BulkAddPaymentModal.tsx
  2. +73
    -0
      src/components/CreateProject/PaymentSummary.tsx
  3. +51
    -4
      src/components/CreateProject/ProjectTotalFee.tsx
  4. +3
    -2
      src/components/LoginPage/LoginForm.tsx
  5. +35
    -5
      src/components/LoginPage/LoginPage.tsx
  6. +18
    -0
      src/theme/devias-material-kit/colors.ts
  7. +10
    -1
      src/theme/devias-material-kit/palette.ts

+ 18
- 1
src/components/CreateProject/BulkAddPaymentModal.tsx Parādīt failu

@@ -73,6 +73,7 @@ const BulkAddPaymentModal: React.FC<Props> = ({

const { register, reset, trigger, formState, watch, control } =
useForm<BulkAddPaymentForm>({
mode: "onTouched",
defaultValues: { dateType: "monthly", dateReference: dayjs() },
});

@@ -87,7 +88,12 @@ const BulkAddPaymentModal: React.FC<Props> = ({
description,
} = formValues;

if (numberOfEntries > 0 && amountToDivide && description) {
if (
Number.isInteger(numberOfEntries) &&
numberOfEntries > 0 &&
amountToDivide &&
description
) {
const dividedAmount = amountToDivide / numberOfEntries;
return Array(numberOfEntries)
.fill(undefined)
@@ -157,6 +163,17 @@ const BulkAddPaymentModal: React.FC<Props> = ({
{...register("numberOfEntries", {
valueAsNumber: true,
required: t("Required"),
validate: (value) => {
if (!value) {
return t("Required");
} else if (value < 0) {
return t("Number must be positive");
} else if (!Number.isInteger(value)) {
return t("Number must be an integer");
} else {
return true;
}
},
})}
error={Boolean(formState.errors.numberOfEntries)}
helperText={formState.errors.numberOfEntries?.message}


+ 73
- 0
src/components/CreateProject/PaymentSummary.tsx Parādīt failu

@@ -0,0 +1,73 @@
import { useMemo } from "react";
import StyledDataGrid from "../StyledDataGrid";
import { GridColDef, GridValidRowModel } from "@mui/x-data-grid";
import { useTranslation } from "react-i18next";
import dayjs from "dayjs";
import { moneyFormatter, OUTPUT_DATE_FORMAT } from "@/app/utils/formatUtil";
import { CreateProjectInputs } from "@/app/api/projects/actions";
import { useFormContext } from "react-hook-form";
import { TaskGroup } from "@/app/api/tasks";

interface Props {
taskGroups: TaskGroup[];
}

interface Row extends GridValidRowModel {
taskStage: string;
description: string;
date: string;
amount: number;
}

const PaymentSummary: React.FC<Props> = ({ taskGroups }) => {
const { t } = useTranslation();

const { watch } = useFormContext<CreateProjectInputs>();
const milestones = watch("milestones");
const rows = useMemo<Row[]>(() => {
return taskGroups.flatMap((group) => {
const payments = milestones[group.id]?.payments || [];
return payments.map(({ description, date, amount, id }) => ({
id,
taskStage: group.name,
description,
date,
amount,
}));
});
}, [milestones, taskGroups]);

const columns = useMemo<GridColDef<GridValidRowModel>[]>(
() => [
{ field: "taskStage", headerName: t("Task Stage"), width: 300 },
{
field: "description",
headerName: t("Payment Milestone Description"),
width: 300,
},
{
field: "date",
headerName: t("Payment Milestone Date"),
width: 200,
type: "date",
valueFormatter(params) {
return dayjs(params.value).format(OUTPUT_DATE_FORMAT);
},
},
{
field: "amount",
headerName: t("Payment Milestone Amount"),
width: 300,
type: "number",
valueFormatter(params) {
return moneyFormatter.format(params.value);
},
},
],
[t],
);

return <StyledDataGrid columns={columns} rows={rows} />;
};

export default PaymentSummary;

+ 51
- 4
src/components/CreateProject/ProjectTotalFee.tsx Parādīt failu

@@ -1,21 +1,51 @@
import { CreateProjectInputs } from "@/app/api/projects/actions";
import { TaskGroup } from "@/app/api/tasks";
import { moneyFormatter } from "@/app/utils/formatUtil";
import { Divider, Stack, Typography } from "@mui/material";
import React from "react";
import {
Button,
Divider,
Modal,
Paper,
Stack,
SxProps,
Typography,
} from "@mui/material";
import React, { useCallback, useState } from "react";
import { useFormContext } from "react-hook-form";
import { useTranslation } from "react-i18next";
import PaymentSummary from "./PaymentSummary";

interface Props {
taskGroups: TaskGroup[];
}

const modalSx: SxProps = {
position: "absolute",
top: "50%",
left: "50%",
transform: "translate(-50%, -50%)",
width: "90%",
maxHeight: "90%",
padding: 3,
display: "flex",
flexDirection: "column",
gap: 2,
};

const ProjectTotalFee: React.FC<Props> = ({ taskGroups }) => {
const { t } = useTranslation();
const { watch } = useFormContext<CreateProjectInputs>();
const milestones = watch("milestones");
const expectedTotalFee = watch("expectedProjectFee");

const [paymentSummaryOpen, setPaymentSummaryOpen] = useState(false);
const closePaymentSummary = useCallback(() => {
setPaymentSummaryOpen(false);
}, []);
const openPaymentSummary = useCallback(() => {
setPaymentSummaryOpen(true);
}, []);

let projectTotal = 0;

return (
@@ -37,9 +67,24 @@ const ProjectTotalFee: React.FC<Props> = ({ taskGroups }) => {
</Stack>
);
})}
<Button
variant="outlined"
size="small"
sx={{ alignSelf: "flex-start" }}
onClick={openPaymentSummary}
>
{t("View payment breakdown")}
</Button>
<Modal open={paymentSummaryOpen} onClose={closePaymentSummary}>
<Paper sx={modalSx}>
<PaymentSummary taskGroups={taskGroups} />
</Paper>
</Modal>
<Divider sx={{ paddingBlockStart: 2 }} />
<Stack direction="row" justifyContent="space-between">
<Typography variant="h6">{t("Sum of Payment Milestone Fee")}</Typography>
<Typography variant="h6">
{t("Sum of Payment Milestone Fee")}
</Typography>
<Typography>{moneyFormatter.format(projectTotal)}</Typography>
</Stack>
<Divider sx={{ paddingBlockStart: 2 }} />
@@ -49,7 +94,9 @@ const ProjectTotalFee: React.FC<Props> = ({ taskGroups }) => {
</Stack>
{projectTotal !== expectedTotalFee && (
<Typography variant="caption" color="warning.main" alignSelf="flex-end">
{t("Sum of Payment Milestone Fee should be same as the expected total fee!")}
{t(
"Sum of Payment Milestone Fee should be same as the expected total fee!",
)}
</Typography>
)}
</Stack>


+ 3
- 2
src/components/LoginPage/LoginForm.tsx Parādīt failu

@@ -1,6 +1,6 @@
"use client";

import { FormHelperText } from "@mui/material";
import { FormHelperText, SxProps } from "@mui/material";
import Button from "@mui/material/Button";
import Stack from "@mui/material/Stack";
import TextField from "@mui/material/TextField";
@@ -31,7 +31,7 @@ const getHumanFriendlyErrorMessage = (
}
};

const LoginForm: React.FC = () => {
const LoginForm: React.FC<{ sx?: SxProps }> = ({ sx }) => {
const { t } = useTranslation("login");
const {
register,
@@ -65,6 +65,7 @@ const LoginForm: React.FC = () => {
margin={5}
component="form"
onSubmit={handleSubmit(onSubmit)}
sx={sx}
>
<Typography variant="h1">{t("Sign In")}</Typography>
<TextField


+ 35
- 5
src/components/LoginPage/LoginPage.tsx Parādīt failu

@@ -7,14 +7,44 @@ import { Box } from "@mui/material";
const LoginPage = () => {
return (
<Grid container height="100vh">
<Grid item sm sx={{ backgroundColor: 'neutral.000', display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Box sx={{ width: '100%', padding: 5, paddingBlockStart: 10, display: 'flex', alignItems: 'center', justifyContent: 'center', svg: { maxHeight: 120 } }}>
<Grid
item
xs={12}
md={6}
sx={{
backgroundColor: "neutral.000",
display: "flex",
alignItems: "center",
justifyContent: "center",
flexGrow: 1,
}}
>
<Box
sx={{
width: "100%",
padding: 5,
paddingBlockStart: 10,
display: "flex",
alignItems: "center",
justifyContent: "center",
svg: { maxHeight: 120 },
}}
>
<Logo />
</Box>
</Grid>
<Grid item xs={12} sm={8} lg={5} sx={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }}>
<Paper square sx={{ width: '100%', padding: 5 }}>
<LoginForm />
<Grid item xs={12} md={6} sx={{ height: { md: "100%" }, flexGrow: 1 }}>
<Paper
square
sx={{
height: "100%",
width: "100%",
padding: { lg: 5, md: 3 },
display: "flex",
alignItems: "center",
}}
>
<LoginForm sx={{ flex: 1 }} />
</Paper>
</Grid>
</Grid>


+ 18
- 0
src/theme/devias-material-kit/colors.ts Parādīt failu

@@ -11,7 +11,25 @@ export const neutral = {
900: "#111927",
};

// export const primary = {
// lightest: "#F5F7FF",
// light: "#EBEEFE",
// main: "#6366F1",
// dark: "#4338CA",
// darkest: "#312E81",
// contrastText: "#FFFFFF",
// };

export const primary = {
lightest: "#f9fff5",
light: "#f9feeb",
main: "#8dba00",
dark: "#638a01",
darkest: "#4a5f14",
contrastText: "#FFFFFF",
};

export const secondary = {
lightest: "#F5F7FF",
light: "#EBEEFE",
main: "#6366F1",


+ 10
- 1
src/theme/devias-material-kit/palette.ts Parādīt failu

@@ -1,6 +1,14 @@
import { common } from "@mui/material/colors";
import { PaletteOptions } from "@mui/material/styles";
import { error, primary, info, neutral, success, warning } from "./colors";
import {
error,
primary,
secondary,
info,
neutral,
success,
warning,
} from "./colors";

const palette = {
action: {
@@ -20,6 +28,7 @@ const palette = {
info,
mode: "light",
primary,
secondary,
success,
text: {
primary: neutral[900],


Notiek ielāde…
Atcelt
Saglabāt