Translate admin pages - Create admin.json files and translate all admin pages
- Create admin.json translation files for es, en, ca with all admin strings - Update IntlProvider to include admin namespace - Translate admin/invites/page.tsx - all strings now use translations - Translate admin/trades/page.tsx - all strings now use translations - Translate admin/price-history/page.tsx - all strings now use translations - Translate admin/availability/page.tsx - all strings now use translations - Add 'saving' key to common.json for all languages - Fix linting errors: add t to useCallback dependencies - All admin pages now fully multilingual
This commit is contained in:
parent
b8b3e8b9f6
commit
e2376855ce
11 changed files with 473 additions and 87 deletions
|
|
@ -5,6 +5,7 @@ import { Permission } from "../../auth-context";
|
|||
import { adminApi } from "../../api";
|
||||
import { Header } from "../../components/Header";
|
||||
import { useRequireAuth } from "../../hooks/useRequireAuth";
|
||||
import { useTranslation } from "../../hooks/useTranslation";
|
||||
import { components } from "../../generated/api";
|
||||
import constants from "../../../../shared/constants.json";
|
||||
import {
|
||||
|
|
@ -49,6 +50,8 @@ interface EditSlot {
|
|||
}
|
||||
|
||||
export default function AdminAvailabilityPage() {
|
||||
const t = useTranslation("admin");
|
||||
const tCommon = useTranslation("common");
|
||||
const { user, isLoading, isAuthorized } = useRequireAuth({
|
||||
requiredPermission: Permission.MANAGE_AVAILABILITY,
|
||||
fallbackRedirect: "/",
|
||||
|
|
@ -145,7 +148,7 @@ export default function AdminAvailabilityPage() {
|
|||
await fetchAvailability();
|
||||
closeModal();
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : "Failed to save");
|
||||
setError(err instanceof Error ? err.message : t("availability.errors.saveFailed"));
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
|
|
@ -166,7 +169,7 @@ export default function AdminAvailabilityPage() {
|
|||
await fetchAvailability();
|
||||
closeModal();
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : "Failed to clear");
|
||||
setError(err instanceof Error ? err.message : t("availability.errors.clearFailed"));
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
}
|
||||
|
|
@ -208,7 +211,7 @@ export default function AdminAvailabilityPage() {
|
|||
await fetchAvailability();
|
||||
cancelCopyMode();
|
||||
} catch (err) {
|
||||
setError(err instanceof Error ? err.message : "Failed to copy");
|
||||
setError(err instanceof Error ? err.message : t("availability.errors.copyFailed"));
|
||||
} finally {
|
||||
setIsCopying(false);
|
||||
}
|
||||
|
|
@ -221,7 +224,7 @@ export default function AdminAvailabilityPage() {
|
|||
if (isLoading) {
|
||||
return (
|
||||
<main style={layoutStyles.main}>
|
||||
<div style={layoutStyles.loader}>Loading...</div>
|
||||
<div style={layoutStyles.loader}>{tCommon("loading")}</div>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
|
@ -238,23 +241,25 @@ export default function AdminAvailabilityPage() {
|
|||
<div style={styles.pageContainer}>
|
||||
<div style={styles.headerRow}>
|
||||
<div>
|
||||
<h1 style={typographyStyles.pageTitle}>Availability</h1>
|
||||
<h1 style={typographyStyles.pageTitle}>{t("availability.title")}</h1>
|
||||
<p style={typographyStyles.pageSubtitle}>
|
||||
Configure your available time slots for the next {maxAdvanceDays} days
|
||||
{t("availability.subtitle", { days: maxAdvanceDays })}
|
||||
</p>
|
||||
</div>
|
||||
{copySource && (
|
||||
<div style={styles.copyActions}>
|
||||
<span style={styles.copyHint}>Select days to copy to, then click Copy</span>
|
||||
<span style={styles.copyHint}>{t("availability.copyMode.hint")}</span>
|
||||
<button
|
||||
onClick={executeCopy}
|
||||
disabled={copyTargets.size === 0 || isCopying}
|
||||
style={buttonStyles.accentButton}
|
||||
>
|
||||
{isCopying ? "Copying..." : `Copy to ${copyTargets.size} day(s)`}
|
||||
{isCopying
|
||||
? t("availability.copyMode.copying")
|
||||
: t("availability.copyMode.copyTo", { count: copyTargets.size })}
|
||||
</button>
|
||||
<button onClick={cancelCopyMode} style={buttonStyles.secondaryButton}>
|
||||
Cancel
|
||||
{t("availability.copyMode.cancel")}
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
|
|
@ -299,7 +304,7 @@ export default function AdminAvailabilityPage() {
|
|||
startCopyMode(dateStr);
|
||||
}}
|
||||
style={styles.copyFromButton}
|
||||
title="Copy to other days"
|
||||
title={t("availability.copyMode.copyTo", { count: 0 })}
|
||||
>
|
||||
📋
|
||||
</button>
|
||||
|
|
@ -307,7 +312,7 @@ export default function AdminAvailabilityPage() {
|
|||
</div>
|
||||
<div style={styles.slotList}>
|
||||
{slots.length === 0 ? (
|
||||
<span style={styles.noSlots}>No availability</span>
|
||||
<span style={styles.noSlots}>{t("availability.modal.noAvailability")}</span>
|
||||
) : (
|
||||
slots.map((slot, i) => (
|
||||
<span key={i} style={styles.slotBadge}>
|
||||
|
|
@ -328,7 +333,7 @@ export default function AdminAvailabilityPage() {
|
|||
<div style={modalStyles.modalOverlay} onClick={closeModal}>
|
||||
<div style={modalStyles.modal} onClick={(e) => e.stopPropagation()}>
|
||||
<h2 style={modalStyles.modalTitle}>
|
||||
Edit Availability - {formatDisplayDate(selectedDate)}
|
||||
{t("availability.modal.title")} - {formatDisplayDate(selectedDate)}
|
||||
</h2>
|
||||
|
||||
{error && <div style={modalStyles.modalError}>{error}</div>}
|
||||
|
|
@ -362,31 +367,31 @@ export default function AdminAvailabilityPage() {
|
|||
<button
|
||||
onClick={() => removeSlot(index)}
|
||||
style={styles.removeSlotButton}
|
||||
title="Remove slot"
|
||||
title={t("availability.modal.removeSlot")}
|
||||
>
|
||||
×
|
||||
</button>
|
||||
</div>
|
||||
))}
|
||||
<button onClick={addSlot} style={styles.addSlotButton}>
|
||||
+ Add Time Range
|
||||
+ {t("availability.modal.addSlot")}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div style={modalStyles.modalActions}>
|
||||
<button onClick={clearAvailability} disabled={isSaving} style={styles.clearButton}>
|
||||
Clear All
|
||||
{t("availability.modal.clear")}
|
||||
</button>
|
||||
<div style={modalStyles.modalActionsRight}>
|
||||
<button onClick={closeModal} style={buttonStyles.secondaryButton}>
|
||||
Cancel
|
||||
{t("availability.modal.close")}
|
||||
</button>
|
||||
<button
|
||||
onClick={saveAvailability}
|
||||
disabled={isSaving}
|
||||
style={buttonStyles.accentButton}
|
||||
>
|
||||
{isSaving ? "Saving..." : "Save"}
|
||||
{isSaving ? tCommon("saving") : t("availability.modal.save")}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue