import { ReloadOutlined, SaveOutlined } from '@ant-design/icons'; import { Alert, App, Button, Card, Checkbox, Flex, Form, Input, InputNumber, Select, Space, Spin, Typography } from 'antd'; import { useCallback, useEffect, useState } from 'react'; import { DEFAULT_APP_CONFIG, getWeeklyScheduleOptions, saveAppConfigToServer, type AppConfig, type PlanCostTimeUnit, } from './appConfig'; import './SharedAppSettingsPage.css'; const { Paragraph, Text, Title } = Typography; const PLAN_COST_TIME_UNIT_OPTIONS: Array<{ value: PlanCostTimeUnit; label: string }> = [ { value: 'hour', label: '시간' }, { value: 'minute', label: '분' }, { value: 'second', label: '초' }, ]; type SharedAppSettingsPageProps = { shareToken: string; }; type SharedAppSettingsFormValue = AppConfig; export function SharedAppSettingsPage({ shareToken }: SharedAppSettingsPageProps) { const { message } = App.useApp(); const [form] = Form.useForm(); const [isLoading, setIsLoading] = useState(true); const [isSaving, setIsSaving] = useState(false); const [errorMessage, setErrorMessage] = useState(''); const [savedConfig, setSavedConfig] = useState(DEFAULT_APP_CONFIG); const loadConfig = useCallback(async () => { setIsLoading(true); setErrorMessage(''); try { const response = await fetch('/api/app-config', { headers: { 'X-Chat-Share-Token': shareToken, }, cache: 'no-store', }); if (!response.ok) { const payload = (await response.json().catch(() => null)) as { message?: string } | null; throw new Error(payload?.message || '앱 설정을 불러오지 못했습니다.'); } const payload = (await response.json()) as { config?: AppConfig }; const nextConfig = payload.config ?? DEFAULT_APP_CONFIG; setSavedConfig(nextConfig); form.setFieldsValue(nextConfig); } catch (error) { setErrorMessage(error instanceof Error ? error.message : '앱 설정을 불러오지 못했습니다.'); } finally { setIsLoading(false); } }, [form, shareToken]); useEffect(() => { void loadConfig(); }, [loadConfig]); const handleSave = useCallback( async (values: SharedAppSettingsFormValue) => { setIsSaving(true); setErrorMessage(''); try { const saved = await saveAppConfigToServer(values, { shareToken, skipAutomationNotifications: true, }); setSavedConfig(saved); form.setFieldsValue(saved); message.success('앱 설정을 저장했습니다.'); } catch (error) { setErrorMessage(error instanceof Error ? error.message : '앱 설정 저장에 실패했습니다.'); } finally { setIsSaving(false); } }, [form, message, shareToken], ); if (isLoading) { return (
); } return (
앱 설정 공유 링크에서 허용된 핵심 앱 설정만 바로 수정합니다.
{errorMessage ? : null} form={form} layout="vertical" initialValues={savedConfig} onFinish={(values) => void handleSave(values)} >
채팅방 알림 수신 자동 새로고침 사용 장싱 처리 필수 main 자동 반영 생성 후 에디터 열기 일일 업무일지 자동 생성 스크린샷 포함 변경 파일 포함 명령 로그 포함
알림 토큰 등록과 업데이트 확인처럼 현재 기기 상태가 필요한 항목은 공유 링크에서 제외했습니다.
); }