feat(apikey): API Key 검토 모달 예상 요청량 수정 기능

- 검토 모달에서 예상 요청량 셀렉트박스로 수정 가능
- 승인 시 adjustedDailyRequestLimit 전달

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
HYOJIN 2026-04-14 13:58:40 +09:00
부모 5ce1ca233d
커밋 dfee04f703
2개의 변경된 파일28개의 추가작업 그리고 5개의 파일을 삭제

파일 보기

@ -75,6 +75,7 @@ const KeyAdminPage = () => {
const [reviewComment, setReviewComment] = useState(''); const [reviewComment, setReviewComment] = useState('');
const [adjustedFromDate, setAdjustedFromDate] = useState(''); const [adjustedFromDate, setAdjustedFromDate] = useState('');
const [adjustedToDate, setAdjustedToDate] = useState(''); const [adjustedToDate, setAdjustedToDate] = useState('');
const [adjustedDailyLimit, setAdjustedDailyLimit] = useState('');
const [activeReviewTab, setActiveReviewTab] = useState<'info' | 'apis'>('info'); const [activeReviewTab, setActiveReviewTab] = useState<'info' | 'apis'>('info');
const [showRejectConfirm, setShowRejectConfirm] = useState(false); const [showRejectConfirm, setShowRejectConfirm] = useState(false);
const [showApproveConfirm, setShowApproveConfirm] = useState(false); const [showApproveConfirm, setShowApproveConfirm] = useState(false);
@ -169,6 +170,7 @@ const KeyAdminPage = () => {
setReviewComment(req.reviewComment || ''); setReviewComment(req.reviewComment || '');
setAdjustedFromDate(req.usageFromDate ? req.usageFromDate.split('T')[0] : ''); setAdjustedFromDate(req.usageFromDate ? req.usageFromDate.split('T')[0] : '');
setAdjustedToDate(req.usageToDate ? req.usageToDate.split('T')[0] : ''); setAdjustedToDate(req.usageToDate ? req.usageToDate.split('T')[0] : '');
setAdjustedDailyLimit(req.dailyRequestEstimate != null ? String(req.dailyRequestEstimate) : '');
setActiveReviewTab('info'); setActiveReviewTab('info');
setShowRejectConfirm(false); setShowRejectConfirm(false);
setShowApproveConfirm(false); setShowApproveConfirm(false);
@ -185,6 +187,7 @@ const KeyAdminPage = () => {
setReviewComment(''); setReviewComment('');
setAdjustedFromDate(req.usageFromDate ? req.usageFromDate.split('T')[0] : ''); setAdjustedFromDate(req.usageFromDate ? req.usageFromDate.split('T')[0] : '');
setAdjustedToDate(req.usageToDate ? req.usageToDate.split('T')[0] : ''); setAdjustedToDate(req.usageToDate ? req.usageToDate.split('T')[0] : '');
setAdjustedDailyLimit(req.dailyRequestEstimate != null ? String(req.dailyRequestEstimate) : '');
setActiveReviewTab('info'); setActiveReviewTab('info');
setShowRejectConfirm(false); setShowRejectConfirm(false);
setShowApproveConfirm(false); setShowApproveConfirm(false);
@ -217,6 +220,7 @@ const KeyAdminPage = () => {
adjustedApiIds: status === 'APPROVED' ? Array.from(adjustedApiIds) : undefined, adjustedApiIds: status === 'APPROVED' ? Array.from(adjustedApiIds) : undefined,
adjustedFromDate: status === 'APPROVED' && adjustedFromDate ? adjustedFromDate : undefined, adjustedFromDate: status === 'APPROVED' && adjustedFromDate ? adjustedFromDate : undefined,
adjustedToDate: status === 'APPROVED' && adjustedToDate ? adjustedToDate : undefined, adjustedToDate: status === 'APPROVED' && adjustedToDate ? adjustedToDate : undefined,
adjustedDailyRequestLimit: status === 'APPROVED' && adjustedDailyLimit ? Number(adjustedDailyLimit) : undefined,
}); });
if (res.success) { if (res.success) {
@ -896,11 +900,29 @@ const KeyAdminPage = () => {
</div> </div>
<span className="text-xs text-gray-500 dark:text-gray-500"> </span> <span className="text-xs text-gray-500 dark:text-gray-500"> </span>
</div> </div>
{isReviewReadOnly ? (
<p className="text-sm font-semibold text-gray-900 dark:text-gray-100 pl-10"> <p className="text-sm font-semibold text-gray-900 dark:text-gray-100 pl-10">
{selectedRequest.dailyRequestEstimate != null {selectedRequest.dailyRequestEstimate != null
? `${Number(selectedRequest.dailyRequestEstimate).toLocaleString()}건/일` ? `${Number(selectedRequest.dailyRequestEstimate).toLocaleString()}건/일`
: '-'} : '-'}
</p> </p>
) : (
<div className="pl-10">
<select
value={adjustedDailyLimit}
onChange={(e) => setAdjustedDailyLimit(e.target.value)}
className="w-full border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-700 text-gray-900 dark:text-gray-100 rounded-lg px-2 py-1 text-sm focus:ring-2 focus:ring-blue-500 focus:outline-none"
>
<option value=""></option>
<option value="100">100 </option>
<option value="500">100~500</option>
<option value="1000">500~1,000</option>
<option value="5000">1,000~5,000</option>
<option value="10000">5,000~10,000</option>
<option value="50000">10,000 </option>
</select>
</div>
)}
<p className="text-xs text-gray-500 dark:text-gray-500 pl-10 mt-0.5">{totalApiCount} API</p> <p className="text-xs text-gray-500 dark:text-gray-500 pl-10 mt-0.5">{totalApiCount} API</p>
</div> </div>
</div> </div>

파일 보기

@ -65,6 +65,7 @@ export interface ApiKeyRequestReviewDto {
adjustedApiIds?: number[]; adjustedApiIds?: number[];
adjustedFromDate?: string; adjustedFromDate?: string;
adjustedToDate?: string; adjustedToDate?: string;
adjustedDailyRequestLimit?: number;
} }
export interface Permission { export interface Permission {