Feature batch: Projects, Recurrence, Group settings, Bug fixes

- Projects CRUD API + invite members
- Task recurrence (daily/weekly/monthly) with auto-creation
- Group time zones + GPS locations settings
- i18n fallback fix (no more undefined labels)
- UX: action buttons in one row
- Chat/Calendar: relative API URLs
- DB: task_assignments, projects tables, recurrence column

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-29 13:49:25 +00:00
parent fc39029ce3
commit b4b8439f80
14 changed files with 1173 additions and 136 deletions

View File

@@ -22,14 +22,14 @@ const MESSAGES: Record<Locale, Messages> = { cs, he, ru, ua };
const STORAGE_KEY = "taskteam_language";
function getNestedValue(obj: unknown, path: string): string {
function getNestedValue(obj: unknown, path: string): string | undefined {
const keys = path.split(".");
let current: unknown = obj;
for (const key of keys) {
if (current == null || typeof current !== "object") return path;
if (current == null || typeof current !== "object") return undefined;
current = (current as Record<string, unknown>)[key];
}
return typeof current === "string" ? current : path;
return typeof current === "string" ? current : undefined;
}
interface I18nContextType {
@@ -75,7 +75,10 @@ export function I18nProvider({ children }: { children: ReactNode }) {
const t = useCallback(
(key: string): string => {
return getNestedValue(MESSAGES[locale], key);
const value = getNestedValue(MESSAGES[locale], key);
if (value !== undefined) return value;
// Fallback: return last segment of the key (the raw value) instead of "undefined"
return key.split(".").pop() || key;
},
[locale]
);