Skip to content

Commit

Permalink
fix: add status labels to the admin side tables
Browse files Browse the repository at this point in the history
- also removes the unnecessary width restriction for the page container
- also fixes Tag typing
  • Loading branch information
vincit-matu committed Oct 3, 2024
1 parent fde60d9 commit e8e0f93
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 18 deletions.
37 changes: 33 additions & 4 deletions apps/admin-ui/src/spa/notifications/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ import styled from "styled-components";
import {
type BannerNotificationNode,
BannerNotificationOrderingChoices,
useBannerNotificationsAdminListQuery,
BannerNotificationsAdminFragment,
BannerNotificationState,
useBannerNotificationsAdminListQuery,
} from "@gql/gql-types";
import { H1 } from "common/src/common/typography";
import { Container } from "@/styles/layout";
Expand All @@ -17,7 +18,14 @@ import { GQL_MAX_RESULTS_PER_QUERY } from "@/common/const";
import { CustomTable } from "@/component/Table";
import { filterNonNullable } from "common/src/helpers";
import { More } from "@/component/More";
import { TableLink } from "@/styles/util";
import { TableLink, TableStatusLabel } from "@/styles/util";
import type { StatusLabelType } from "common/src/tags";
import {
IconCheck,
IconClock,
IconPen,
IconQuestionCircleFill,
} from "hds-react";

const notificationUrl = (pk: number) => `/messaging/notifications/${pk}`;

Expand All @@ -27,14 +35,35 @@ const HeaderContainer = styled.div`
align-items: center;
`;

const getStatusLabelProps = (
state: BannerNotificationState | null | undefined
): { type: StatusLabelType; icon: JSX.Element } => {
switch (state) {
case BannerNotificationState.Draft:
return { type: "draft", icon: <IconPen ariaHidden /> };
case BannerNotificationState.Scheduled:
return { type: "info", icon: <IconClock ariaHidden /> };
case BannerNotificationState.Active:
return { type: "success", icon: <IconCheck ariaHidden /> };
default:
return { type: "info", icon: <IconQuestionCircleFill ariaHidden /> };
}
};

// Tila, Nimi, Voimassa alk, Voimassa asti, Kohderyhmä, Tyyppi
const getColConfig = (t: TFunction) => [
{
headerName: t("Notifications.headings.state"),
key: "state",
isSortable: true,
transform: (notification: NonNullable<BannerNotificationNode>) =>
t(`Notifications.state.${notification.state ?? "noState"}`),
transform: (notification: NonNullable<BannerNotificationNode>) => {
const labelProps = getStatusLabelProps(notification.state);
return (
<TableStatusLabel type={labelProps.type} icon={labelProps.icon}>
{t(`Notifications.state.${notification.state ?? "noState"}`)}
</TableStatusLabel>
);
},
},
{
headerName: t("Notifications.headings.name"),
Expand Down
74 changes: 68 additions & 6 deletions apps/admin-ui/src/spa/reservation-units/ReservationUnitsTable.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
import React from "react";
import { useTranslation } from "react-i18next";
import type { TFunction } from "i18next";
import type { SearchReservationUnitsQuery } from "@gql/gql-types";
import {
ReservationUnitPublishingState,
ReservationUnitReservationState,
SearchReservationUnitsQuery,
} from "@gql/gql-types";
import { truncate } from "@/helpers";
import { getReservationUnitUrl } from "@/common/urls";
import { CustomTable } from "@/component/Table";
import { MAX_NAME_LENGTH } from "@/common/const";
import { TableLink } from "@/styles/util";
import { TableLink, TableStatusLabel } from "@/styles/util";
import {
IconCheck,
IconClock,
IconEye,
IconEyeCrossed,
IconLock,
IconPen,
IconQuestionCircleFill,
} from "hds-react";
import type { StatusLabelType } from "common/src/tags";

type ReservationUnitList = NonNullable<
SearchReservationUnitsQuery["reservationUnits"]
Expand All @@ -21,6 +35,42 @@ type Props = {
isLoading?: boolean;
};

const getStatusLabelProps = (
state: ReservationUnitReservationState | null | undefined
): { type: StatusLabelType; icon: JSX.Element } => {
switch (state) {
case ReservationUnitReservationState.Reservable:
return { type: "success", icon: <IconEye /> };
case ReservationUnitReservationState.ReservationClosed:
return { type: "neutral", icon: <IconLock /> };
case ReservationUnitReservationState.ScheduledReservation:
case ReservationUnitReservationState.ScheduledClosing:
case ReservationUnitReservationState.ScheduledPeriod:
return { type: "info", icon: <IconClock /> };
default:
return { type: "info", icon: <IconQuestionCircleFill /> };
}
};

const getPublishingStateProps = (
state: ReservationUnitPublishingState | null | undefined
): { type: StatusLabelType; icon: JSX.Element } => {
switch (state) {
case ReservationUnitPublishingState.ScheduledHiding:
case ReservationUnitPublishingState.ScheduledPeriod:
case ReservationUnitPublishingState.ScheduledPublishing:
return { type: "info", icon: <IconClock ariaHidden /> };
case ReservationUnitPublishingState.Published:
return { type: "success", icon: <IconCheck ariaHidden /> };
case ReservationUnitPublishingState.Draft:
return { type: "draft", icon: <IconPen ariaHidden /> };
case ReservationUnitPublishingState.Hidden:
return { type: "neutral", icon: <IconEyeCrossed ariaHidden /> };
default:
return { type: "neutral", icon: <IconQuestionCircleFill ariaHidden /> };
}
};

const getColConfig = (t: TFunction) => [
{
headerName: t("ReservationUnits.headings.name"),
Expand Down Expand Up @@ -71,14 +121,26 @@ const getColConfig = (t: TFunction) => [
{
headerName: t("ReservationUnits.headings.state"),
key: "state",
transform: ({ publishingState }: ReservationUnitNode) =>
t(`ReservationUnits.state.${publishingState}`),
transform: ({ publishingState }: ReservationUnitNode) => {
const labelProps = getPublishingStateProps(publishingState);
return (
<TableStatusLabel type={labelProps.type} icon={labelProps.icon}>
{t(`ReservationUnits.state.${publishingState}`)}
</TableStatusLabel>
);
},
},
{
headerName: t("ReservationUnits.headings.reservationState"),
key: "reservationState",
transform: ({ reservationState }: ReservationUnitNode) =>
t(`ReservationUnits.reservationState.${reservationState}`),
transform: ({ reservationState }: ReservationUnitNode) => {
const labelProps = getStatusLabelProps(reservationState);
return (
<TableStatusLabel type={labelProps.type} icon={labelProps.icon}>
{t(`ReservationUnits.reservationState.${reservationState}`)}
</TableStatusLabel>
);
},
},
];

Expand Down
73 changes: 68 additions & 5 deletions apps/admin-ui/src/spa/reservations/ReservationsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import React from "react";
import { useTranslation } from "react-i18next";
import type { TFunction } from "i18next";
import { memoize } from "lodash";
import type { ReservationsQuery } from "@gql/gql-types";
import {
OrderStatus,
ReservationsQuery,
ReservationStateChoice,
} from "@gql/gql-types";
import { truncate } from "@/helpers";
import { getReservationUrl } from "@/common/urls";
import {
Expand All @@ -12,7 +16,16 @@ import {
} from "@/common/util";
import { CustomTable } from "@/component/Table";
import { MAX_NAME_LENGTH } from "@/common/const";
import { TableLink } from "@/styles/util";
import { TableLink, TableStatusLabel } from "@/styles/util";
import type { StatusLabelType } from "common/src/tags";
import {
IconCheck,
IconCogwheel,
IconCross,
IconEuroSign,
IconPen,
IconQuestionCircleFill,
} from "hds-react";

type ReservationTableColumn = {
headerName: string;
Expand All @@ -32,6 +45,45 @@ type Props = {
reservations: ReservationType[];
};

const getStatusLabelProps = (
state: ReservationStateChoice | null | undefined
): { type: StatusLabelType; icon: JSX.Element } => {
switch (state) {
case ReservationStateChoice.Created:
return { type: "draft", icon: <IconPen ariaHidden /> };
case ReservationStateChoice.Denied:
return { type: "error", icon: <IconCross ariaHidden /> };
case ReservationStateChoice.WaitingForPayment:
return { type: "alert", icon: <IconEuroSign ariaHidden /> };
case ReservationStateChoice.Cancelled:
return { type: "neutral", icon: <IconCross ariaHidden /> };
case ReservationStateChoice.Confirmed:
return { type: "success", icon: <IconCheck ariaHidden /> };
case ReservationStateChoice.RequiresHandling:
return { type: "info", icon: <IconCogwheel ariaHidden /> };
default:
return { type: "info", icon: <IconQuestionCircleFill ariaHidden /> };
}
};

const getPaymentStatusLabelType = (
status: OrderStatus | null | undefined
): StatusLabelType => {
switch (status) {
case OrderStatus.Refunded:
case OrderStatus.Paid:
return "success";
case OrderStatus.Expired:
return "error";
case OrderStatus.PaidManually:
case OrderStatus.Draft:
return "alert";
case OrderStatus.Cancelled:
default:
return "neutral";
}
};

const getColConfig = (t: TFunction): ReservationTableColumn[] => [
{
headerName: t("Reservations.headings.id"),
Expand Down Expand Up @@ -92,15 +144,26 @@ const getColConfig = (t: TFunction): ReservationTableColumn[] => [
if (!order) {
return "-";
}
return t(`Payment.status.${order.status}`);
const labelType = getPaymentStatusLabelType(order.status);
return (
<TableStatusLabel type={labelType} icon={<IconEuroSign />}>
{t(`Payment.status.${order.status}`)}
</TableStatusLabel>
);
},
},
{
headerName: t("Reservations.headings.state"),
key: "state",
isSortable: true,
transform: ({ state }: ReservationType) =>
t(`RequestedReservation.state.${state}`),
transform: ({ state }: ReservationType) => {
const labelProps = getStatusLabelProps(state);
return (
<TableStatusLabel type={labelProps.type} icon={labelProps.icon}>
{t(`RequestedReservation.state.${state}`)}
</TableStatusLabel>
);
},
},
];

Expand Down
2 changes: 0 additions & 2 deletions apps/admin-ui/src/styles/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -58,8 +58,6 @@ export const Container = styled.div`
display: grid;
gap: var(--spacing-layout-2-xs);
max-width: var(--container-width-xl);
margin: var(--spacing-layout-2-xs) var(--spacing-layout-m);
@media (max-width: ${breakpoints.m}) {
Expand Down
6 changes: 6 additions & 0 deletions apps/admin-ui/src/styles/util.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Dialog } from "hds-react";
import styled from "styled-components";
import { Link } from "react-router-dom";
import StatusLabel from "common/src/components/StatusLabel";

export const Seranwrap = styled.div`
height: 200%;
Expand Down Expand Up @@ -56,3 +57,8 @@ export const Element = styled.div<{ $wide?: boolean; $start?: boolean }>`
$wide ? "1 / -1" : $start ? "1 / span 1" : "auto / span 1"};
max-width: var(--prose-width);
`;

// StatusLabels expand the table cell without this, as they're too high au naturel
export const TableStatusLabel = styled(StatusLabel)`
margin-block: -6px;
`;
2 changes: 1 addition & 1 deletion packages/common/src/components/Tag.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ type TagPropsType = {
onClick?: () => void;
id?: string;
children: React.ReactNode;
} & Pick<React.HTMLAttributes<HTMLDivElement>, "role">;
};

const ColoredTag = styled(StyledTag)<{ $type: StatusLabelType }>`
&& {
Expand Down

0 comments on commit e8e0f93

Please sign in to comment.