diff --git a/client/components/admin/AddUserCard.jsx b/client/components/admin/AddUserCard.tsx
similarity index 89%
rename from client/components/admin/AddUserCard.jsx
rename to client/components/admin/AddUserCard.tsx
index ccb2c92..16ae09e 100644
--- a/client/components/admin/AddUserCard.jsx
+++ b/client/components/admin/AddUserCard.tsx
@@ -1,18 +1,19 @@
-import React, { useState } from 'react';
+import { useState } from 'react';
import { toast } from 'sonner';
import { api } from '@/api';
+import { errMessage } from '@/lib/utils';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
-export default function AddUserCard({ onCreated }) {
+export default function AddUserCard({ onCreated }: { onCreated: () => void }) {
const [username, setUsername] = useState('');
const [password, setPassword] = useState('');
const [loading, setLoading] = useState(false);
const [error, setError] = useState('');
- const handleCreate = async (e) => {
+ const handleCreate = async (e: React.FormEvent) => {
e.preventDefault();
setError('');
@@ -32,7 +33,7 @@ export default function AddUserCard({ onCreated }) {
setError('');
onCreated();
} catch (err) {
- const errorMessage = err.message || 'Failed to create user.';
+ const errorMessage = errMessage(err, 'Failed to create user.');
setError(errorMessage);
toast.error(errorMessage);
} finally {
diff --git a/client/components/admin/PrivacyAdminCard.jsx b/client/components/admin/PrivacyAdminCard.jsx
deleted file mode 100644
index 2fffc99..0000000
--- a/client/components/admin/PrivacyAdminCard.jsx
+++ /dev/null
@@ -1,59 +0,0 @@
-import React, { useState, useEffect } from 'react';
-import { toast } from 'sonner';
-import { api } from '@/api';
-import { Card, CardHeader, CardTitle, CardContent } from '@/components/ui/card';
-import { FieldRow, Toggle } from './adminShared';
-
-export default function PrivacyAdminCard() {
- const [geoEnabled, setGeoEnabled] = useState(false);
- const [loading, setLoading] = useState(true);
- const [saving, setSaving] = useState(false);
-
- useEffect(() => {
- api.privacySettings()
- .then(d => { setGeoEnabled(!!d.geolocation_enabled); })
- .catch(() => toast.error('Failed to load privacy settings'))
- .finally(() => setLoading(false));
- }, []);
-
- async function toggleGeo(next) {
- setSaving(true);
- try {
- const d = await api.setPrivacySettings({ geolocation_enabled: next });
- setGeoEnabled(!!d.geolocation_enabled);
- toast.success(next ? 'Geolocation enabled' : 'Geolocation disabled');
- } catch {
- toast.error('Failed to update privacy settings');
- } finally {
- setSaving(false);
- }
- }
-
- return (
-
- When enabled, new-device logins resolve the login IP to a city/region via{' '}
- ip-api.com over plain HTTP. Disable to keep
- all login data on-device. Location data is encrypted at rest.
-