diff --git a/src/components/Buttons/CopyButton/styles.ts b/src/components/Buttons/CopyButton/styles.ts index 3c5d721..34c5551 100644 --- a/src/components/Buttons/CopyButton/styles.ts +++ b/src/components/Buttons/CopyButton/styles.ts @@ -7,6 +7,7 @@ const StyledButton = styled(Button)(({ theme }) => ({ float: "right", alignSelf: "flex-end", color: theme.palette.primary.main, + cursor: "pointer", })); export default StyledButton; diff --git a/src/pages/Deployment/BasicInfo/index.tsx b/src/pages/Deployment/BasicInfo/index.tsx index 0d49620..303ed75 100644 --- a/src/pages/Deployment/BasicInfo/index.tsx +++ b/src/pages/Deployment/BasicInfo/index.tsx @@ -1,7 +1,10 @@ /* eslint-disable no-underscore-dangle */ import CopyButton from "@Components/Buttons/CopyButton"; import CarpErrorCardComponent from "@Components/CarpErrorCardComponent"; -import { useParticipantGroupsAccountsAndStatus } from "@Utils/queries/participants"; +import { + useParticipantGroupsAccountsAndStatus, + useStopParticipantGroup, +} from "@Utils/queries/participants"; import { ParticipantGroup } from "@carp-dk/client"; import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; @@ -22,7 +25,8 @@ import { StyledStatusText, } from "./styles"; import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined"; -import { useCreateSummary, useExports } from "@Utils/queries/studies"; +import { useCreateSummary } from "@Utils/queries/studies"; +import DeleteConfirmationModal from "@Components/DeleteConfirmationModal"; const BasicInfo = () => { const { deploymentId, id: studyId } = useParams(); @@ -33,7 +37,28 @@ const BasicInfo = () => { isLoading: participantDataLoading, error: participantError, } = useParticipantGroupsAccountsAndStatus(studyId); + const stopDeployment = useStopParticipantGroup(studyId); + const [deployment, setDeployment] = useState(null); + const [openStopConfirmationModal, setOpenStopConfirmationModal] = + useState(false); + + const handleStopDeployment = () => { + setOpenStopConfirmationModal(false); + stopDeployment.mutate(deployment.participantGroupId); + }; + + const confirmationModalProps = { + open: openStopConfirmationModal, + onClose: () => setOpenStopConfirmationModal(false), + onConfirm: handleStopDeployment, + title: "Stop deployment", + description: + "The deployment will be permanently stopped and will no longer be running.", + boldText: "You can not undo this action.", + checkboxLabel: "I'm sure I want to stop it", + actionButtonLabel: "Stop", + }; const generateExport = useCreateSummary(); @@ -59,6 +84,16 @@ const BasicInfo = () => { return ( <> + @@ -83,7 +118,10 @@ const BasicInfo = () => { {!deployment.deploymentStatus.__type.includes("Stopped") && ( - + setOpenStopConfirmationModal(true)} + > {t("common:stop_deployment")} diff --git a/src/pages/Deployment/BasicInfo/styles.ts b/src/pages/Deployment/BasicInfo/styles.ts index 490b9e5..57a5be1 100644 --- a/src/pages/Deployment/BasicInfo/styles.ts +++ b/src/pages/Deployment/BasicInfo/styles.ts @@ -27,23 +27,6 @@ export const Right = styled("div")({ }, }); -export const AccountIcon = styled("div")(({ theme }) => ({ - width: 40, - height: 40, - backgroundColor: theme.palette.company.isotype, - borderRadius: "50%", - position: "relative", - marginRight: 8, -})); - -export const Initials = styled(Typography)(({ theme }) => ({ - color: theme.palette.common.white, - position: "absolute", - top: "52%", - left: "50%", - transform: "translate(-50%, -50%)", -})); - export const StyledDivider = styled(Divider)(({ theme }) => ({ borderColor: theme.palette.grey[300], borderWidth: 1, @@ -53,26 +36,6 @@ export const StyledDivider = styled(Divider)(({ theme }) => ({ height: 64, })); -export const RemindersContainer = styled(Button)({ - display: "flex", - alignItems: "center", - gap: 4, - textTransform: "none", -}); - -export const ReminderText = styled(Typography)(({ theme }) => ({ - color: theme.palette.primary.main, -})); - -export const Name = styled(Typography)(({ theme }) => ({ - color: theme.palette.text.primary, -})); - -export const Email = styled(Typography)(({ theme }) => ({ - marginLeft: 16, - color: theme.palette.grey[500], -})); - export const SecondaryText = styled(Typography)(({ theme }) => ({ color: theme.palette.text.secondary, marginTop: 4, @@ -95,7 +58,6 @@ export const StyledStatusText = styled(Typography, { textTransform: "uppercase", })); - export const ExportButton = styled(Button)(({ theme }) => ({ border: `1px solid ${theme.palette.grey[700]}`, borderRadius: 16, diff --git a/src/pages/Deployment/Devices/index.tsx b/src/pages/Deployment/Devices/index.tsx index ee5a69f..671f29d 100644 --- a/src/pages/Deployment/Devices/index.tsx +++ b/src/pages/Deployment/Devices/index.tsx @@ -15,16 +15,18 @@ import { CancelButton, Description, DescriptionContainer, + DeviceCard, + DeviceName, + DeviceRow, ModalBox, StyledStatusDot, + SubDeviceRow, Title, } from "./styles"; import { t } from "i18next"; import { useStudyDetails } from "@Utils/queries/studies"; import { getDeviceIcon } from "@Utils/utility"; -import { title } from "process"; import { CarpServiceError } from "@carp-dk/client"; -import { randomUUID } from "crypto"; import { v4 } from "uuid"; const Devices = () => { @@ -187,22 +189,9 @@ const Devices = () => { {devices && devices.map(({ primaryDevice, connections }) => ( - - + setModalState({ open: true, @@ -219,48 +208,30 @@ const Devices = () => { }} justifyContent={"center"} > - + {getDeviceIcon(primaryDevice.type)} {primaryDevice.name} - + - + {connections.map((connection) => { return ( - - + + {getDeviceIcon(connection.type)} {connection.name} - + - + ); })} - + ))} diff --git a/src/pages/Deployment/Devices/styles.ts b/src/pages/Deployment/Devices/styles.ts index 1c92c4a..0cbbf88 100644 --- a/src/pages/Deployment/Devices/styles.ts +++ b/src/pages/Deployment/Devices/styles.ts @@ -1,4 +1,4 @@ -import { Typography, Button } from "@mui/material"; +import { Typography, Button, Stack } from "@mui/material"; import { styled } from "@Utils/theme"; import { getDeviceStatusColor } from "@Utils/utility"; @@ -13,7 +13,6 @@ export const StyledStatusDot = styled("div", { alignSelf: "center", })); - export const ModalBox = styled("div")(({ theme }) => ({ display: "flex", flexDirection: "column", @@ -43,22 +42,11 @@ export const Description = styled(Typography)(({ theme }) => ({ display: "inline", })); -export const BoldText = styled(Typography)(({ theme }) => ({ - color: theme.palette.text.primary, - display: "inline", - marginLeft: 4, -})); - export const Bottom = styled("div")({ display: "flex", justifyContent: "space-between", }); -export const ButtonsContainer = styled("div")({ - display: "flex", - gap: 16, -}); - export const CancelButton = styled(Button)({ textTransform: "capitalize", borderRadius: 16, @@ -70,3 +58,36 @@ export const ActionButton = styled(Button)({ textTransform: "capitalize", borderRadius: 16, }); + +export const DeviceCard = styled(Stack)(({ theme }) => ({ + gap: "8px", + border: "1px solid", + borderColor: theme.palette.grey[300], + borderRadius: "16px", + display: "flex", + width: "100%", + maxWidth: "25%", + padding: "16px 16px", +})); + +export const DeviceRow = styled(Stack)({ + gap: "16px", + padding: "4px 8px 4px 4px", + display: "grid", + gridTemplateColumns: "1fr 8px 16px", + justifyContent: "center", +}); + +export const SubDeviceRow = styled(Stack)({ + gap: "16px", + padding: "4px 8px 4px 24px", + display: "grid", + gridTemplateColumns: "1fr 8px 16px", + justifyContent: "center", +}); + +export const DeviceName = styled(Stack)({ + gap: "8px", + display: "grid", + gridTemplateColumns: "18px 1fr", +}); diff --git a/src/pages/Deployment/InformedConsentCard/index.tsx b/src/pages/Deployment/InformedConsentCard/index.tsx index f5c63e9..223b0df 100644 --- a/src/pages/Deployment/InformedConsentCard/index.tsx +++ b/src/pages/Deployment/InformedConsentCard/index.tsx @@ -22,7 +22,6 @@ import { useEffect, useState } from "react"; import { InformedConsent } from "@carp-dk/client/models/InputDataTypes"; import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined"; import { formatDateTime } from "@Utils/utility"; - interface FileInfo { data: string; fileName: string; @@ -87,7 +86,7 @@ const InformedConsentCard = () => { if (!v) return false; return ((v as any).__type as string).includes("informed_consent"); }); - const roleConsents = participantData.roles.map((v) => { + const roleConsents = (participantData.roles as any as Array).map((v) => { const c = (v as any).data .toArray() .find((d) => d.__type.includes("informed_consent")); @@ -127,7 +126,7 @@ const InformedConsentCard = () => { {participant.firstName && participant.lastName && ( {`${participant.firstName} ${participant.lastName}`} - )} + ) || {participant.participantId}} {consent && ( diff --git a/src/pages/Deployment/Participants/index.tsx b/src/pages/Deployment/Participants/index.tsx index 899ac79..7af0e32 100644 --- a/src/pages/Deployment/Participants/index.tsx +++ b/src/pages/Deployment/Participants/index.tsx @@ -1,6 +1,6 @@ import CarpErrorCardComponent from "@Components/CarpErrorCardComponent"; import { useParticipantGroupsAccountsAndStatus } from "@Utils/queries/participants"; -import { Box, Stack, Typography } from "@mui/material"; +import { Stack, Typography } from "@mui/material"; import { useEffect, useState } from "react"; import { useParams } from "react-router-dom"; import { ParticipantGroup } from "@carp-dk/client"; @@ -35,10 +35,7 @@ const Participants = () => { if (error) { return ( - + ); } diff --git a/src/pages/Deployment/Participants/styles.ts b/src/pages/Deployment/Participants/styles.ts index c6d7cc9..64d0084 100644 --- a/src/pages/Deployment/Participants/styles.ts +++ b/src/pages/Deployment/Participants/styles.ts @@ -1,29 +1,6 @@ -import { Accordion, AccordionSummary, Typography } from "@mui/material"; +import { Typography } from "@mui/material"; import { styled } from "@Utils/theme"; -export const StyledAccordion = styled(Accordion)({ - padding: "10px 24px", - marginBottom: 32, - borderRadius: 8, - "::before": { - display: "none", - }, -}); - -export const SyledAccordionSummary = styled(AccordionSummary)({ - padding: "0", -}); - -export const Title = styled(Typography)(({ theme }) => ({ - color: theme.palette.primary.main, - padding: "0", -})); - -export const Right = styled("div")({ - display: "flex", - alignItems: "center", -}); - export const AccountIcon = styled("div")(({ theme }) => ({ width: 28, height: 28, diff --git a/src/pages/Deployments/DeploymentCard/index.tsx b/src/pages/Deployments/DeploymentCard/index.tsx index 696c9f5..98f8c3d 100644 --- a/src/pages/Deployments/DeploymentCard/index.tsx +++ b/src/pages/Deployments/DeploymentCard/index.tsx @@ -1,24 +1,18 @@ /* eslint-disable no-underscore-dangle */ import CopyButton from "@Components/Buttons/CopyButton"; -import DeleteConfirmationModal from "@Components/DeleteConfirmationModal"; -import { useStopParticipantGroup } from "@Utils/queries/participants"; -import { useCreateSummary } from "@Utils/queries/studies"; import { ParticipantGroup } from "@carp-dk/client"; -import FileDownloadOutlinedIcon from "@mui/icons-material/FileDownloadOutlined"; import KeyboardArrowDownRoundedIcon from "@mui/icons-material/KeyboardArrowDownRounded"; import { Skeleton, Typography } from "@mui/material"; import { useEffect, useMemo, useState } from "react"; -import { useParams } from "react-router-dom"; +import { useNavigate, useParams } from "react-router-dom"; import DateTooltip from "../DateTooltip"; import ParticipantRecord from "../ParticipantRecord"; import { - DownloadButton, HorizontalStatusContainer, IdContainer, MinimizeButton, Names, ParticipantsContainer, - StopDeploymentButton, StyledCard, StyledDivider, StyledStatusDot, @@ -39,11 +33,10 @@ const DeploymentCard = ({ allDeploymentCount, }: Props) => { const { id: studyId } = useParams(); - const stopDeployment = useStopParticipantGroup(studyId); + const navigate = useNavigate(); + const [isCardOpen, setIsCardOpen] = useState(false); - const [openStopConfirmationModal, setOpenStopConfirmationModal] = - useState(false); - const createSummary = useCreateSummary(); + useEffect(() => { if (openCardCount === allDeploymentCount) setIsCardOpen(true); if (openCardCount === 0) setIsCardOpen(false); @@ -60,10 +53,6 @@ const DeploymentCard = ({ }); }; - const handleStopDeployment = () => { - setOpenStopConfirmationModal(false); - stopDeployment.mutate(deployment.participantGroupId); - }; let names = useMemo( () => deployment.participants @@ -76,36 +65,20 @@ const DeploymentCard = ({ [deployment.participants], ); - const createAndDownloadSummary = (event) => { - event.stopPropagation(); - createSummary.mutate({ - studyId, - deploymentIds: [deployment.participantGroupId], - }); - }; - - const handleStopDeploymentButtonClick = (event) => { - event.stopPropagation(); - setOpenStopConfirmationModal(true); - }; - - const confirmationModalProps = { - open: openStopConfirmationModal, - onClose: () => setOpenStopConfirmationModal(false), - onConfirm: handleStopDeployment, - title: "Stop deployment", - description: - "The deployment will be permanently stopped and will no longer be running.", - boldText: "You can not undo this action.", - checkboxLabel: "I'm sure I want to stop it", - actionButtonLabel: "Stop", - }; if (names[0] === ",") names = ""; else if (names.length > 30) names = `${names.slice(0, 30)}...`; return ( - - + + + navigate( + `/studies/${studyId}/participants/deployments/${deployment.participantGroupId}`, + ) + } + > {names && names[0].length > 0 ? names : Generated deployment} @@ -129,15 +102,6 @@ const DeploymentCard = ({ } /> - {deployment.deploymentStatus.stoppedOn ? ( -
- ) : ( - handleStopDeploymentButtonClick(event)} - > - Stop deployment - - )} Deployment ID: {deployment.participantGroupId} @@ -147,11 +111,6 @@ const DeploymentCard = ({ idType="Deployment" /> - - createAndDownloadSummary(event)}> - Export Data - - handleCardToggle(event)} @@ -174,16 +133,6 @@ const DeploymentCard = ({ /> ))} - ); }; @@ -204,7 +153,6 @@ export const DeploymentSkeletonCard = () => { height={14} /> - @@ -216,14 +164,6 @@ export const DeploymentSkeletonCard = () => { height={19} /> - - {}} open={false}> diff --git a/src/pages/Deployments/DeploymentCard/styles.ts b/src/pages/Deployments/DeploymentCard/styles.ts index f8724e9..65b532b 100644 --- a/src/pages/Deployments/DeploymentCard/styles.ts +++ b/src/pages/Deployments/DeploymentCard/styles.ts @@ -9,17 +9,22 @@ export const GreyText = styled(Typography)(({ theme }) => ({ export const TopContainer = styled("div")({ borderRadius: "16px", display: "grid", - gridTemplateColumns: "1fr 20px 200px 100px 400px auto auto 40px", + gridTemplateColumns: "1fr 40px 220px 400px 60px", alignItems: "center", marginBottom: 16, width: "100%", padding: "2px 0 2px 16px", - cursor: "pointer", }); -export const Names = styled(Typography)({ +export const Names = styled(Typography)(({ theme }) => ({ overflow: "hidden", -}); + minWidth: "200px", + cursor: "pointer", + ":hover": { + textDecoration: "underline", + color: theme.palette.primary.main, + }, +})); export const HorizontalStatusContainer = styled("div")({ display: "flex", diff --git a/src/pages/Deployments/ParticipantRecord/index.tsx b/src/pages/Deployments/ParticipantRecord/index.tsx index d501015..4947e33 100644 --- a/src/pages/Deployments/ParticipantRecord/index.tsx +++ b/src/pages/Deployments/ParticipantRecord/index.tsx @@ -17,6 +17,7 @@ import { useMemo } from "react"; import { useNavigate, useParams } from "react-router-dom"; import { AccountIcon, + EmailContainer, Initials, NameContainer, RoleContainer, @@ -33,13 +34,10 @@ type Props = { }; const ParticipantRecord = ({ - deploymentId, participantData, participantStatus, deviceStatusList, }: Props) => { - const { id: studyId } = useParams(); - const navigate = useNavigate(); const participantRole = participantStatus.assignedParticipantRoles.roleNames[0]; const participantDeviceRoleName = @@ -53,7 +51,7 @@ const ParticipantRecord = ({ const lastDataUpload = useMemo(() => { const lastData = participantData.dateOfLastDataUpload; if (!lastData) { - return ""; + return "Last data: Today"; } const elapsedDays = calculateDaysPassedFromDate(lastData.toString()); if (elapsedDays === 0) { @@ -63,32 +61,28 @@ const ParticipantRecord = ({ }, [participantData.dateOfLastDataUpload]); return ( - - navigate( - `/studies/${studyId}/participants/deployments/${deploymentId}/participants/${participantData.participantId}`, - ) - } - > - - - {!participantData.firstName || !participantData.lastName - ? participantRole[0] - : `${participantData.firstName[0]}${participantData.lastName[0]}`} - - - - {participantData.email ?? } - + + + + + {!participantData.firstName + ? participantRole[0] + : `${participantData.firstName[0]}${participantData.lastName[0]}`} + + + + {participantData.email ?? } + + - {participantData.firstName && participantData.lastName && ( - <> - - + <> + + {participantData.firstName && ( + {participantData.firstName} {participantData.lastName} - - )} + )} + diff --git a/src/pages/Deployments/ParticipantRecord/styles.ts b/src/pages/Deployments/ParticipantRecord/styles.ts index 6564682..f39083c 100644 --- a/src/pages/Deployments/ParticipantRecord/styles.ts +++ b/src/pages/Deployments/ParticipantRecord/styles.ts @@ -4,34 +4,37 @@ import { getDeviceStatusColor } from "@Utils/utility"; export const StyledContainer = styled("div")({ display: "grid", - gridTemplateColumns: "40px 6fr 5fr 4fr 4fr 2fr 4fr", + gridTemplateColumns: "185px 150px 1fr 2fr 3fr 2fr", overflow: "hidden", alignItems: "center", - columnGap: 12, + columnGap: "16px", textDecoration: "none", color: "inherit", padding: "12px 16px", - "&:hover": { - backgroundColor: "rgba(0, 0, 0, 0.04)", - }, +}); + +export const EmailContainer = styled("div")({ + display: "flex", + alignItems: "center", + gap: "15px", }); export const NameContainer = styled("div")({ display: "flex", alignItems: "center", - gap: 6, + gap: "4px", }); export const RoleContainer = styled("div")({ alignItems: "center", display: "flex", - gap: 6, + gap: "4px", }); export const StatusContainer = styled("div")({ display: "flex", alignItems: "center", - gap: 6, + gap: "4px", }); export const ActivityDataContainer = styled("div")({ @@ -64,6 +67,7 @@ export const MinimizeButton = styled(Button, { export const AccountIcon = styled("div")(({ theme }) => ({ width: 28, height: 28, + minWidth: 28, backgroundColor: theme.palette.company.isotype, borderRadius: "50%", position: "relative",