mirror of
https://github.com/QuantumNous/new-api.git
synced 2026-09-12 23:30:35 +00:00
Revert the following commits: -308e3e347feat(web): polish themed data views and add task log details -b2a890e75fix: Fontsource asset resolution across workspace layouts -9d1ca545erefactor(web): refine data-table cards and pricing page layout -0918bdb49refactor(web): consolidate design-system primitives and responsive data views -262ab9312style(web): unify design system across default frontend
167 lines
4.2 KiB
React
Vendored
167 lines
4.2 KiB
React
Vendored
/*
|
|
Copyright (C) 2025 QuantumNous
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU Affero General Public License as
|
|
published by the Free Software Foundation, either version 3 of the
|
|
License, or (at your option) any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU Affero General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Affero General Public License
|
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
For commercial licensing, please contact support@quantumnous.com
|
|
*/
|
|
|
|
import { useState, useEffect } from 'react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { API, showError, showSuccess } from '../../helpers';
|
|
import { useTableCompactMode } from '../common/useTableCompactMode';
|
|
|
|
export const useSubscriptionsData = () => {
|
|
const { t } = useTranslation();
|
|
const [compactMode, setCompactMode] = useTableCompactMode('subscriptions');
|
|
|
|
// State management
|
|
const [allPlans, setAllPlans] = useState([]);
|
|
const [loading, setLoading] = useState(true);
|
|
|
|
// Pagination (client-side for now)
|
|
const [activePage, setActivePage] = useState(1);
|
|
const [pageSize, setPageSize] = useState(10);
|
|
|
|
// Drawer states
|
|
const [showEdit, setShowEdit] = useState(false);
|
|
const [editingPlan, setEditingPlan] = useState(null);
|
|
const [sheetPlacement, setSheetPlacement] = useState('left'); // 'left' | 'right'
|
|
|
|
// Load subscription plans
|
|
const loadPlans = async () => {
|
|
setLoading(true);
|
|
try {
|
|
const res = await API.get('/api/subscription/admin/plans');
|
|
if (res.data?.success) {
|
|
const next = res.data.data || [];
|
|
setAllPlans(next);
|
|
|
|
// Keep page in range after data changes
|
|
const totalPages = Math.max(1, Math.ceil(next.length / pageSize));
|
|
setActivePage((p) => Math.min(p || 1, totalPages));
|
|
} else {
|
|
showError(res.data?.message || t('加载失败'));
|
|
}
|
|
} catch (e) {
|
|
showError(t('请求失败'));
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
// Refresh data
|
|
const refresh = async () => {
|
|
await loadPlans();
|
|
};
|
|
|
|
const handlePageChange = (page) => {
|
|
setActivePage(page);
|
|
};
|
|
|
|
const handlePageSizeChange = (size) => {
|
|
setPageSize(size);
|
|
setActivePage(1);
|
|
};
|
|
|
|
// Update plan enabled status (single endpoint)
|
|
const setPlanEnabled = async (planRecordOrId, enabled) => {
|
|
const planId =
|
|
typeof planRecordOrId === 'number'
|
|
? planRecordOrId
|
|
: planRecordOrId?.plan?.id;
|
|
if (!planId) return;
|
|
setLoading(true);
|
|
try {
|
|
const res = await API.patch(`/api/subscription/admin/plans/${planId}`, {
|
|
enabled: !!enabled,
|
|
});
|
|
if (res.data?.success) {
|
|
showSuccess(enabled ? t('已启用') : t('已禁用'));
|
|
await loadPlans();
|
|
} else {
|
|
showError(res.data?.message || t('操作失败'));
|
|
}
|
|
} catch (e) {
|
|
showError(t('请求失败'));
|
|
} finally {
|
|
setLoading(false);
|
|
}
|
|
};
|
|
|
|
// Modal control functions
|
|
const closeEdit = () => {
|
|
setShowEdit(false);
|
|
setEditingPlan(null);
|
|
};
|
|
|
|
const openCreate = () => {
|
|
setSheetPlacement('left');
|
|
setEditingPlan(null);
|
|
setShowEdit(true);
|
|
};
|
|
|
|
const openEdit = (planRecord) => {
|
|
setSheetPlacement('right');
|
|
setEditingPlan(planRecord);
|
|
setShowEdit(true);
|
|
};
|
|
|
|
// Initialize data on component mount
|
|
useEffect(() => {
|
|
loadPlans();
|
|
}, []);
|
|
|
|
const planCount = allPlans.length;
|
|
const plans = allPlans.slice(
|
|
Math.max(0, (activePage - 1) * pageSize),
|
|
Math.max(0, (activePage - 1) * pageSize) + pageSize,
|
|
);
|
|
|
|
return {
|
|
// Data state
|
|
plans,
|
|
planCount,
|
|
loading,
|
|
|
|
// Modal state
|
|
showEdit,
|
|
editingPlan,
|
|
sheetPlacement,
|
|
setShowEdit,
|
|
setEditingPlan,
|
|
|
|
// UI state
|
|
compactMode,
|
|
setCompactMode,
|
|
|
|
// Pagination
|
|
activePage,
|
|
pageSize,
|
|
handlePageChange,
|
|
handlePageSizeChange,
|
|
|
|
// Actions
|
|
loadPlans,
|
|
setPlanEnabled,
|
|
refresh,
|
|
closeEdit,
|
|
openCreate,
|
|
openEdit,
|
|
|
|
// Translation
|
|
t,
|
|
};
|
|
};
|