feat(34-02): extract hardcoded strings from thread/candidate components
- CandidateCard: replace all hardcoded titles and badge text with t() - CandidateListItem: add useTranslation, replace winner/delete/open labels and +/- Notes badge - CandidateForm: add useTranslation, replace all form labels, placeholders, validation errors, submit button - ComparisonTable: move STATUS_LABELS inside component with t(), replace all ATTRIBUTE_ROWS labels, View button, impact row labels - StatusBadge: refactor STATUS_CONFIG to STATUS_ICONS + runtime STATUS_LABELS via t() - CreateThreadModal: replace title, thread name label, category label, placeholder, cancel/submit buttons, error messages - AddToThreadModal: replace modal titles, labels, placeholders, back/cancel/submit buttons, error messages - threads.json: extend candidateForm with category, notes, pros, cons, product link labels and all placeholders
This commit is contained in:
@@ -1,9 +1,11 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { useCategories } from "../hooks/useCategories";
|
||||
import { useCreateThread } from "../hooks/useThreads";
|
||||
import { useUIStore } from "../stores/uiStore";
|
||||
|
||||
export function CreateThreadModal() {
|
||||
const { t } = useTranslation(["threads", "common"]);
|
||||
const isOpen = useUIStore((s) => s.createThreadModalOpen);
|
||||
const closeModal = useUIStore((s) => s.closeCreateThreadModal);
|
||||
|
||||
@@ -38,11 +40,11 @@ export function CreateThreadModal() {
|
||||
e.preventDefault();
|
||||
const trimmed = name.trim();
|
||||
if (!trimmed) {
|
||||
setError("Thread name is required");
|
||||
setError(t("create.nameRequired"));
|
||||
return;
|
||||
}
|
||||
if (categoryId === null) {
|
||||
setError("Please select a category");
|
||||
setError(t("create.selectCategory"));
|
||||
return;
|
||||
}
|
||||
setError(null);
|
||||
@@ -55,7 +57,7 @@ export function CreateThreadModal() {
|
||||
},
|
||||
onError: (err) => {
|
||||
setError(
|
||||
err instanceof Error ? err.message : "Failed to create thread",
|
||||
err instanceof Error ? err.message : t("create.createFailed"),
|
||||
);
|
||||
},
|
||||
},
|
||||
@@ -77,7 +79,7 @@ export function CreateThreadModal() {
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
onKeyDown={() => {}}
|
||||
>
|
||||
<h2 className="text-lg font-semibold text-gray-900 mb-4">New Thread</h2>
|
||||
<h2 className="text-lg font-semibold text-gray-900 mb-4">{t("create.title")}</h2>
|
||||
|
||||
<form onSubmit={handleSubmit} className="space-y-4">
|
||||
<div>
|
||||
@@ -85,14 +87,14 @@ export function CreateThreadModal() {
|
||||
htmlFor="thread-name"
|
||||
className="block text-sm font-medium text-gray-700 mb-1"
|
||||
>
|
||||
Thread name
|
||||
{t("create.threadName")}
|
||||
</label>
|
||||
<input
|
||||
id="thread-name"
|
||||
type="text"
|
||||
value={name}
|
||||
onChange={(e) => setName(e.target.value)}
|
||||
placeholder="e.g. Lightweight sleeping bag"
|
||||
placeholder={t("create.namePlaceholder")}
|
||||
className="w-full px-3 py-2 border border-gray-200 rounded-lg text-sm focus:outline-none focus:ring-2 focus:ring-gray-400 focus:border-transparent"
|
||||
/>
|
||||
</div>
|
||||
@@ -102,7 +104,7 @@ export function CreateThreadModal() {
|
||||
htmlFor="thread-category"
|
||||
className="block text-sm font-medium text-gray-700 mb-1"
|
||||
>
|
||||
Category
|
||||
{t("create.category")}
|
||||
</label>
|
||||
<select
|
||||
id="thread-category"
|
||||
@@ -126,14 +128,14 @@ export function CreateThreadModal() {
|
||||
onClick={handleClose}
|
||||
className="px-4 py-2 text-sm font-medium text-gray-700 bg-gray-100 hover:bg-gray-200 rounded-lg transition-colors"
|
||||
>
|
||||
Cancel
|
||||
{t("common:actions.cancel")}
|
||||
</button>
|
||||
<button
|
||||
type="submit"
|
||||
disabled={createThread.isPending}
|
||||
className="px-4 py-2 text-sm font-medium text-white bg-gray-700 hover:bg-gray-800 disabled:opacity-50 rounded-lg transition-colors"
|
||||
>
|
||||
{createThread.isPending ? "Creating..." : "Create Thread"}
|
||||
{createThread.isPending ? t("common:actions.creating") : t("create.createThread")}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
Reference in New Issue
Block a user