Phase 1 scaffold: auth for all apps
- Backend: Fastify with two listeners (public + internal), routes, services, DB migration + seed - client_app: Flutter with BLoC, all auth screens (welcome, display name, register, OTP, force-register) - mitra_app: Flutter with BLoC, OTP-only login - control_center: React + Vite, email/password login, mitra/user management, anonymity settings - Docs: phase1 plan, API contract, client app mockup - CLAUDE.md and shared memory for all subprojects Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
45
control_center/src/pages/settings/SettingsPage.jsx
Normal file
45
control_center/src/pages/settings/SettingsPage.jsx
Normal file
@@ -0,0 +1,45 @@
|
||||
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query'
|
||||
import { apiClient } from '../../core/api/api-client'
|
||||
|
||||
const fetchAnonymityConfig = async () => {
|
||||
const res = await apiClient.get('/internal/config/anonymity')
|
||||
return res.data.data
|
||||
}
|
||||
|
||||
const updateAnonymityConfig = async (anonymity_enabled) => {
|
||||
const res = await apiClient.patch('/internal/config/anonymity', { anonymity_enabled })
|
||||
return res.data.data
|
||||
}
|
||||
|
||||
export default function SettingsPage() {
|
||||
const queryClient = useQueryClient()
|
||||
const { data, isLoading } = useQuery({ queryKey: ['config-anonymity'], queryFn: fetchAnonymityConfig })
|
||||
|
||||
const mutation = useMutation({
|
||||
mutationFn: updateAnonymityConfig,
|
||||
onSuccess: () => queryClient.invalidateQueries({ queryKey: ['config-anonymity'] }),
|
||||
})
|
||||
|
||||
if (isLoading) return <div>Loading...</div>
|
||||
|
||||
return (
|
||||
<div>
|
||||
<h1>Settings</h1>
|
||||
|
||||
<section style={{ marginBottom: 24 }}>
|
||||
<h2>Anonymity</h2>
|
||||
<p>Ketika dinonaktifkan, pengguna anonim akan diminta mendaftar setelah sesi selesai.</p>
|
||||
<label style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={data?.anonymity_enabled ?? true}
|
||||
onChange={e => mutation.mutate(e.target.checked)}
|
||||
disabled={mutation.isPending}
|
||||
/>
|
||||
Izinkan pengguna anonim
|
||||
</label>
|
||||
{mutation.isError && <p style={{ color: 'red' }}>Gagal menyimpan.</p>}
|
||||
</section>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user