Address PR review on data request pages
Require a verified viewer email before creating a rights request and validate the free-text fields with the same SafeText bounds the console uses, so this public portal mutation stays safe and bounded. Move myRightsRequests onto the base Query, drop the now-dead count loaders, and order the RECTIFICATION enum value before PORTABILITY so the Postgres sort order matches RightsRequestTypes(). Harden the v2 kit primitives: SegmentedControl keeps equal-width cards (auto-fill), preserves its selection when the active card is toggled, and forwards an accessible name; Field associates its label and error by id/aria instead of wrapping the control in a label. Give the type group an accessible name, require the name field for non-complaint types, use a timezone-stable reference year, drop the underreporting header count, and neutralize the response-deadline copy. Signed-off-by: Émile Ré <emile@probo.com>
This commit is contained in:
@@ -132,7 +132,7 @@ export function RequestsPage({ queryRef }: RequestsPageProps) {
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader title={t("title")} count={requests.length} actions={newRequestButton} />
|
||||
<PageHeader title={t("title")} actions={newRequestButton} />
|
||||
<div className={page()}>
|
||||
<div className={results()}>
|
||||
<ListErrorBoundary
|
||||
|
||||
@@ -34,7 +34,7 @@ import { TextField } from "@probo/ui/src/v2/form/TextField";
|
||||
import { SegmentedControl } from "@probo/ui/src/v2/SegmentedControl/SegmentedControl";
|
||||
import { SegmentedControlItem } from "@probo/ui/src/v2/SegmentedControl/SegmentedControlItem";
|
||||
import { Text } from "@probo/ui/src/v2/typography/Text";
|
||||
import { type FormEvent, useState } from "react";
|
||||
import { type FormEvent, useId, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
|
||||
import {
|
||||
@@ -89,6 +89,7 @@ interface NewRequestFormProps {
|
||||
function NewRequestForm({ onClose, connectionId, viewerEmail, viewerName }: NewRequestFormProps) {
|
||||
const { t } = useTranslation("requests");
|
||||
const [submit, isSubmitting] = useCreateRightsRequest();
|
||||
const typeLabelId = useId();
|
||||
|
||||
const [type, setType] = useState<SubmittableRightsRequestType>("ACCESS");
|
||||
const [name, setName] = useState(viewerName);
|
||||
@@ -148,10 +149,11 @@ function NewRequestForm({ onClose, connectionId, viewerEmail, viewerName }: NewR
|
||||
<DialogBody>
|
||||
<div className={root()}>
|
||||
<div className={label()}>
|
||||
<Text size={2} weight="medium" color="neutral" highContrast>
|
||||
<Text id={typeLabelId} size={2} weight="medium" color="neutral" highContrast>
|
||||
{t("dialog.typeLabel")}
|
||||
</Text>
|
||||
<SegmentedControl
|
||||
aria-labelledby={typeLabelId}
|
||||
value={type}
|
||||
onValueChange={value => setType(value as SubmittableRightsRequestType)}
|
||||
>
|
||||
@@ -173,6 +175,7 @@ function NewRequestForm({ onClose, connectionId, viewerEmail, viewerName }: NewR
|
||||
<TextField
|
||||
value={name}
|
||||
placeholder={t("form.namePlaceholder")}
|
||||
required={!config.nameOptional}
|
||||
onChange={e => setName(e.target.value)}
|
||||
/>
|
||||
</Field>
|
||||
|
||||
@@ -98,7 +98,8 @@ export const rightsRequestFormConfig: Record<
|
||||
// Human-facing reference derived from the created year and a short suffix of the
|
||||
// opaque id (display-only; not a stored sequential number).
|
||||
export function formatRightsRequestReference(id: string, createdAt: string): string {
|
||||
const year = new Date(createdAt).getFullYear();
|
||||
// Use UTC so the reference year is stable regardless of the viewer's timezone.
|
||||
const year = new Date(createdAt).getUTCFullYear();
|
||||
const suffix = id.replace(/[^a-zA-Z0-9]/g, "").slice(-6).toUpperCase();
|
||||
return `REQ-${year}-${suffix}`;
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"submit": "Submit Request",
|
||||
"success": {
|
||||
"title": "Request submitted",
|
||||
"description": "We'll process your request and respond within 30 days.",
|
||||
"description": "We'll process your request and respond within the timeframe required by applicable law.",
|
||||
"close": "Close"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"submit": "Envoyer la demande",
|
||||
"success": {
|
||||
"title": "Demande envoyée",
|
||||
"description": "Nous traiterons votre demande et vous répondrons sous 30 jours.",
|
||||
"description": "Nous traiterons votre demande et vous répondrons dans le délai prévu par la loi applicable.",
|
||||
"close": "Fermer"
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user