Polish business FA layout and wire special-group keys plus SSL sync.
RTL carousels/FABs, special key+title fields, slider gallery fixes, and dashboard SSL sync agent for super-admin. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
co-authored by
Cursor
parent
66004a0fba
commit
672091d1f5
@@ -7,6 +7,7 @@ import { PortfolioCommentsModal } from '../components/PortfolioCommentsModal'
|
||||
import { ConfirmDeleteModal } from '../components/ConfirmDeleteModal'
|
||||
import { Pagination } from '../components/Pagination'
|
||||
import { useToast } from '../context/ToastContext'
|
||||
import { useT } from '../i18n/useT'
|
||||
import { ApiError } from '../lib/api'
|
||||
import {
|
||||
PORTFOLIOS_PER_PAGE,
|
||||
@@ -21,6 +22,7 @@ import styles from './BlogPage.module.css'
|
||||
export function PortfolioListPage() {
|
||||
const navigate = useNavigate()
|
||||
const { showToast } = useToast()
|
||||
const t = useT()
|
||||
const [portfolios, setPortfolios] = useState<Portfolio[]>([])
|
||||
const [totalPortfolios, setTotalPortfolios] = useState(0)
|
||||
const [currentPage, setCurrentPage] = useState(1)
|
||||
@@ -58,7 +60,7 @@ export function PortfolioListPage() {
|
||||
if (err instanceof ApiError) {
|
||||
setError(err.message)
|
||||
} else {
|
||||
setError('Unable to load portfolios.')
|
||||
setError(t('portfolio.list.errorLoad'))
|
||||
}
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
@@ -94,7 +96,6 @@ export function PortfolioListPage() {
|
||||
|
||||
try {
|
||||
if (index === 0) {
|
||||
// First on this page, but not global first — bump above the current band.
|
||||
await updatePortfolio(current.id, { sortOrder: current.sortOrder - 1 })
|
||||
} else {
|
||||
const previous = portfolios[index - 1]
|
||||
@@ -107,13 +108,13 @@ export function PortfolioListPage() {
|
||||
])
|
||||
}
|
||||
}
|
||||
showToast('Portfolio moved up.', 'success')
|
||||
showToast(t('portfolio.list.toast.movedUp'), 'success')
|
||||
await loadPortfolios(currentPage)
|
||||
} catch (err) {
|
||||
if (err instanceof ApiError) {
|
||||
setError(err.message)
|
||||
} else {
|
||||
setError('Unable to move portfolio.')
|
||||
setError(t('portfolio.list.errorMove'))
|
||||
}
|
||||
} finally {
|
||||
setMovingUpId(null)
|
||||
@@ -128,7 +129,7 @@ export function PortfolioListPage() {
|
||||
|
||||
try {
|
||||
await deletePortfolio(deleteTarget.id)
|
||||
showToast('Portfolio removed.', 'success')
|
||||
showToast(t('portfolio.list.toast.removed'), 'success')
|
||||
const nextTotal = totalPortfolios - 1
|
||||
const nextTotalPages = Math.max(1, Math.ceil(nextTotal / PORTFOLIOS_PER_PAGE))
|
||||
const nextPage = currentPage > nextTotalPages ? nextTotalPages : currentPage
|
||||
@@ -139,7 +140,7 @@ export function PortfolioListPage() {
|
||||
if (err instanceof ApiError) {
|
||||
setError(err.message)
|
||||
} else {
|
||||
setError('Unable to delete portfolio.')
|
||||
setError(t('portfolio.list.errorDelete'))
|
||||
}
|
||||
} finally {
|
||||
setIsDeleting(false)
|
||||
@@ -171,9 +172,9 @@ export function PortfolioListPage() {
|
||||
|
||||
<div className={pageStyles.pageHeader}>
|
||||
<div>
|
||||
<h2 className={pageStyles.pageTitle}>My Portfolios</h2>
|
||||
<h2 className={pageStyles.pageTitle}>{t('title.myPortfolios')}</h2>
|
||||
<p className={pageStyles.pageSubtitle}>
|
||||
{totalPortfolios} items · View, edit and manage your portfolio content.
|
||||
{t('portfolio.list.subtitle', { count: totalPortfolios })}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -185,9 +186,9 @@ export function PortfolioListPage() {
|
||||
)}
|
||||
|
||||
{isLoading ? (
|
||||
<p className={styles.empty}>Loading portfolios...</p>
|
||||
<p className={styles.empty}>{t('portfolio.list.loading')}</p>
|
||||
) : portfolios.length === 0 ? (
|
||||
<p className={styles.empty}>No portfolio items found.</p>
|
||||
<p className={styles.empty}>{t('portfolio.list.empty')}</p>
|
||||
) : (
|
||||
<>
|
||||
<div className={pageStyles.gridCols4}>
|
||||
@@ -218,17 +219,17 @@ export function PortfolioListPage() {
|
||||
type="button"
|
||||
className={styles.addFab}
|
||||
onClick={() => navigate('/portfolios/new')}
|
||||
aria-label="Add new portfolio"
|
||||
aria-label={t('portfolio.list.addNew')}
|
||||
>
|
||||
<Plus size={26} strokeWidth={2.5} />
|
||||
</button>
|
||||
|
||||
<ConfirmDeleteModal
|
||||
open={!!deleteTarget}
|
||||
title="Delete Portfolio"
|
||||
title={t('portfolio.list.deleteTitle')}
|
||||
message={
|
||||
deleteTarget
|
||||
? `Are you sure you want to delete "${deleteTarget.title}"? This action cannot be undone.`
|
||||
? t('portfolio.list.deleteMessage', { name: deleteTarget.title })
|
||||
: ''
|
||||
}
|
||||
onConfirm={confirmDelete}
|
||||
|
||||
Reference in New Issue
Block a user