Cleanup pass 2

This commit is contained in:
adilallo
2026-05-22 13:30:47 -06:00
parent b7c804bac8
commit 753220f97b
76 changed files with 1338 additions and 1020 deletions
@@ -5,7 +5,7 @@
* File: agv0VBLiBlcnSAaiAORgPR, node 22078-587823
*/
import { memo, useCallback, useEffect, useState, type FormEvent } from "react";
import { memo, useCallback, useEffect, useMemo, useState, type FormEvent } from "react";
import { AskOrganizerInquiryModalView } from "./AskOrganizerInquiryModal.view";
import type { AskOrganizerInquiryModalProps } from "./AskOrganizerInquiryModal.types";
import { ORGANIZER_INQUIRY_HONEYPOT_FIELD } from "../../../../lib/organizerInquiryConstants";
@@ -14,6 +14,23 @@ import { useTranslation } from "../../../contexts/MessagesContext";
const AskOrganizerInquiryModalContainer = memo<AskOrganizerInquiryModalProps>(
({ isOpen, onClose }) => {
const t = useTranslation("modals.askOrganizerInquiry");
const copy = useMemo(
() => ({
title: t("title"),
description: t("description"),
emailLabel: t("emailLabel"),
emailPlaceholder: t("emailPlaceholder"),
questionLabel: t("questionLabel"),
questionPlaceholder: t("questionPlaceholder"),
submitButton: t("submitButton"),
closeAfterSuccess: t("closeAfterSuccess"),
successTitle: t("successTitle"),
successDescription: t("successDescription"),
ariaDialog: t("ariaDialog"),
honeypotLabel: t("honeypotLabel"),
}),
[t],
);
const [email, setEmail] = useState("");
const [message, setMessage] = useState("");
const [honeypot, setHoneypot] = useState("");
@@ -102,6 +119,7 @@ const AskOrganizerInquiryModalContainer = memo<AskOrganizerInquiryModalProps>(
<AskOrganizerInquiryModalView
isOpen={isOpen}
onClose={onClose}
copy={copy}
email={email}
message={message}
honeypot={honeypot}
@@ -2,3 +2,35 @@ export interface AskOrganizerInquiryModalProps {
isOpen: boolean;
onClose: () => void;
}
export interface AskOrganizerInquiryModalCopy {
title: string;
description: string;
emailLabel: string;
emailPlaceholder: string;
questionLabel: string;
questionPlaceholder: string;
submitButton: string;
closeAfterSuccess: string;
successTitle: string;
successDescription: string;
ariaDialog: string;
honeypotLabel: string;
}
export interface AskOrganizerInquiryModalViewProps
extends AskOrganizerInquiryModalProps {
copy: AskOrganizerInquiryModalCopy;
email: string;
message: string;
honeypot: string;
submitting: boolean;
success: boolean;
formError: string | null;
emailError: boolean;
questionError: boolean;
onEmailChange: (_v: string) => void;
onMessageChange: (_v: string) => void;
onHoneypotChange: (_v: string) => void;
onSubmit: (_e: import("react").FormEvent<HTMLFormElement>) => void;
}
@@ -1,31 +1,14 @@
"use client";
import type { FormEvent } from "react";
import Create from "../Create";
import TextInput from "../../controls/TextInput";
import TextArea from "../../controls/TextArea";
import Button from "../../buttons/Button";
import { useTranslation } from "../../../contexts/MessagesContext";
import {
ASK_ORGANIZER_INQUIRY_FORM_ID,
ORGANIZER_INQUIRY_HONEYPOT_FIELD,
} from "../../../../lib/organizerInquiryConstants";
import type { AskOrganizerInquiryModalProps } from "./AskOrganizerInquiryModal.types";
export type AskOrganizerInquiryModalViewProps = AskOrganizerInquiryModalProps & {
email: string;
message: string;
honeypot: string;
submitting: boolean;
success: boolean;
formError: string | null;
emailError: boolean;
questionError: boolean;
onEmailChange: (_v: string) => void;
onMessageChange: (_v: string) => void;
onHoneypotChange: (_v: string) => void;
onSubmit: (_e: FormEvent<HTMLFormElement>) => void;
};
import type { AskOrganizerInquiryModalViewProps } from "./AskOrganizerInquiryModal.types";
/**
* Figma: Community Rule System — Modal / Ask an Organizer (22078-587823)
@@ -33,6 +16,7 @@ export type AskOrganizerInquiryModalViewProps = AskOrganizerInquiryModalProps &
export function AskOrganizerInquiryModalView({
isOpen,
onClose,
copy,
email,
message,
honeypot,
@@ -46,8 +30,6 @@ export function AskOrganizerInquiryModalView({
onHoneypotChange,
onSubmit,
}: AskOrganizerInquiryModalViewProps) {
const t = useTranslation("modals.askOrganizerInquiry");
const footer = success ? (
<div className="w-full px-1">
<Button
@@ -58,7 +40,7 @@ export function AskOrganizerInquiryModalView({
className="w-full !justify-center"
onClick={onClose}
>
{t("closeAfterSuccess")}
{copy.closeAfterSuccess}
</Button>
</div>
) : (
@@ -72,7 +54,7 @@ export function AskOrganizerInquiryModalView({
className="w-full !justify-center"
disabled={submitting}
>
{t("submitButton")}
{copy.submitButton}
</Button>
</div>
);
@@ -82,22 +64,22 @@ export function AskOrganizerInquiryModalView({
isOpen={isOpen}
onClose={onClose}
backdropVariant="blurredYellow"
title={t("title")}
description={t("description")}
title={copy.title}
description={copy.description}
showBackButton={false}
showNextButton={false}
stepper={false}
ariaLabel={t("ariaDialog")}
ariaLabel={copy.ariaDialog}
footerContent={footer}
footerClassName="!h-auto min-h-[112px] shrink-0 flex flex-col justify-end pb-8 pt-3 px-4"
>
{success ? (
<div className="flex flex-col gap-3 py-2">
<p className="font-inter text-[18px] font-semibold leading-[24px] text-[var(--color-content-default-primary)]">
{t("successTitle")}
{copy.successTitle}
</p>
<p className="font-inter text-[14px] leading-[20px] text-[var(--color-content-default-secondary)]">
{t("successDescription")}
{copy.successDescription}
</p>
</div>
) : (
@@ -120,8 +102,8 @@ export function AskOrganizerInquiryModalView({
type="email"
name="email"
autoComplete="email"
label={t("emailLabel")}
placeholder={t("emailPlaceholder")}
label={copy.emailLabel}
placeholder={copy.emailPlaceholder}
value={email}
onChange={(e) => onEmailChange(e.target.value)}
error={emailError}
@@ -131,8 +113,8 @@ export function AskOrganizerInquiryModalView({
<TextArea
name="message"
label={t("questionLabel")}
placeholder={t("questionPlaceholder")}
label={copy.questionLabel}
placeholder={copy.questionPlaceholder}
value={message}
onChange={(e) => onMessageChange(e.target.value)}
error={questionError}
@@ -146,7 +128,7 @@ export function AskOrganizerInquiryModalView({
className="pointer-events-none absolute left-0 top-0 h-px w-px overflow-hidden opacity-0"
>
<label htmlFor={`${ASK_ORGANIZER_INQUIRY_FORM_ID}-${ORGANIZER_INQUIRY_HONEYPOT_FIELD}`}>
{t("honeypotLabel")}
{copy.honeypotLabel}
</label>
<input
id={`${ASK_ORGANIZER_INQUIRY_FORM_ID}-${ORGANIZER_INQUIRY_HONEYPOT_FIELD}`}
+2 -2
View File
@@ -262,14 +262,14 @@ export default function LoginForm({
<p className="text-center font-inter text-[14px] leading-[20px] text-[var(--color-content-default-tertiary)]">
{t("legalPrefix")}
<Link
href="#"
href={tFooter("legal.termsOfServiceHref")}
className="text-[var(--color-content-default-tertiary)] underline decoration-solid underline-offset-2"
>
{tFooter("legal.termsOfService")}
</Link>
{t("legalAnd")}
<Link
href="#"
href={tFooter("legal.privacyPolicyHref")}
className="text-[var(--color-content-default-tertiary)] underline decoration-solid underline-offset-2"
>
{tFooter("legal.privacyPolicy")}
@@ -1,6 +1,7 @@
"use client";
import { memo } from "react";
import { useTranslation } from "../../../contexts/MessagesContext";
import { ModalFooterView } from "./ModalFooter.view";
import type { ModalFooterProps } from "./ModalFooter.types";
@@ -10,7 +11,17 @@ import type { ModalFooterProps } from "./ModalFooter.types";
* primary/secondary actions.
*/
const ModalFooterContainer = memo<ModalFooterProps>((props) => {
return <ModalFooterView {...props} />;
const t = useTranslation("common");
const resolvedBackText = props.backButtonText ?? t("buttons.back");
const resolvedNextText = props.nextButtonText ?? t("buttons.next");
return (
<ModalFooterView
{...props}
backButtonText={resolvedBackText}
nextButtonText={resolvedNextText}
/>
);
});
ModalFooterContainer.displayName = "ModalFooter";
@@ -1,6 +1,5 @@
"use client";
import { useTranslation } from "../../../contexts/MessagesContext";
import Button from "../../buttons/Button";
import Stepper from "../../progress/Stepper";
import type { ModalFooterProps } from "./ModalFooter.types";
@@ -19,14 +18,6 @@ export function ModalFooterView({
footerContent,
className = "",
}: ModalFooterProps) {
const t = useTranslation("common");
// Use localized defaults if text not provided
const defaultBackText = backButtonText || t("buttons.back");
const defaultNextText = nextButtonText || t("buttons.next");
// Determine if stepper should be shown
// Defaults to true if currentStep and totalSteps are provided, unless explicitly set to false
const shouldShowStepper =
stepperProp !== undefined
? stepperProp
@@ -36,7 +27,6 @@ export function ModalFooterView({
<div
className={`h-[64px] bg-[var(--color-surface-default-primary)] rounded-bl-[var(--radius-300,12px)] rounded-br-[var(--radius-300,12px)] shrink-0 relative ${className}`}
>
{/* Back Button - Absolutely positioned bottom left */}
{showBackButton && (
<div className="absolute left-[16px] top-[12px]">
<Button
@@ -45,19 +35,17 @@ export function ModalFooterView({
size="medium"
onClick={onBack}
>
{defaultBackText}
{backButtonText}
</Button>
</div>
)}
{/* Stepper (Centered) */}
{shouldShowStepper && currentStep && totalSteps && (
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2">
<Stepper active={currentStep} totalSteps={totalSteps} />
</div>
)}
{/* Next Button - Absolutely positioned bottom right */}
{showNextButton && (
<div className="absolute right-[16px] top-[12px]">
<Button
@@ -67,12 +55,11 @@ export function ModalFooterView({
onClick={onNext}
disabled={nextButtonDisabled}
>
{defaultNextText}
{nextButtonText}
</Button>
</div>
)}
{/* Custom Footer Content */}
{footerContent}
</div>
);