mirror of
https://github.com/SECTL/SecScore.git
synced 2026-07-19 19:04:23 +08:00
优化首页按钮组的响应式布局
- 启用 Space 组件的 wrap 属性,允许按钮在空间不足时自动换行 - 使用 useResponsive hook 检测屏幕尺寸 - 根据屏幕尺寸动态调整搜索框、下拉框和按钮的宽度 - 在移动端和平板设备上使用更紧凑的布局 - 添加 flexShrink 属性防止按钮被过度压缩
This commit is contained in:
+171
-89
@@ -1,9 +1,22 @@
|
|||||||
import React, { useState, useEffect, useCallback, useMemo, useRef } from "react"
|
import React, { useState, useEffect, useCallback, useMemo, useRef } from "react"
|
||||||
import { Card, Space, Button, Tag, Input, Select, Modal, Drawer, message, InputNumber, Divider } from "antd"
|
import {
|
||||||
|
Card,
|
||||||
|
Space,
|
||||||
|
Button,
|
||||||
|
Tag,
|
||||||
|
Input,
|
||||||
|
Select,
|
||||||
|
Modal,
|
||||||
|
Drawer,
|
||||||
|
message,
|
||||||
|
InputNumber,
|
||||||
|
Divider,
|
||||||
|
} from "antd"
|
||||||
import { SearchOutlined, DeleteOutlined, UndoOutlined } from "@ant-design/icons"
|
import { SearchOutlined, DeleteOutlined, UndoOutlined } from "@ant-design/icons"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { match, pinyin } from "pinyin-pro"
|
import { match, pinyin } from "pinyin-pro"
|
||||||
import { getAvatarFromExtraJson } from "../utils/studentAvatar"
|
import { getAvatarFromExtraJson } from "../utils/studentAvatar"
|
||||||
|
import { useResponsive } from "../hooks/useResponsive"
|
||||||
|
|
||||||
interface student {
|
interface student {
|
||||||
id: number
|
id: number
|
||||||
@@ -81,6 +94,9 @@ interface HomeProps {
|
|||||||
|
|
||||||
export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) => {
|
export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
|
const breakpoint = useResponsive()
|
||||||
|
const isMobile = breakpoint === "xs" || breakpoint === "sm"
|
||||||
|
const isTablet = breakpoint === "md"
|
||||||
const [students, setStudents] = useState<student[]>([])
|
const [students, setStudents] = useState<student[]>([])
|
||||||
const [reasons, setReasons] = useState<reason[]>([])
|
const [reasons, setReasons] = useState<reason[]>([])
|
||||||
const [rewards, setRewards] = useState<rewardSetting[]>([])
|
const [rewards, setRewards] = useState<rewardSetting[]>([])
|
||||||
@@ -184,7 +200,8 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
if (!(window as any).api) return
|
if (!(window as any).api) return
|
||||||
const res = await (window as any).api.queryEvents({ limit: 1 })
|
const res = await (window as any).api.queryEvents({ limit: 1 })
|
||||||
if (res.success) {
|
if (res.success) {
|
||||||
const latest = Array.isArray(res.data) && res.data.length > 0 ? (res.data[0] as scoreEvent) : null
|
const latest =
|
||||||
|
Array.isArray(res.data) && res.data.length > 0 ? (res.data[0] as scoreEvent) : null
|
||||||
setLatestEvent(latest)
|
setLatestEvent(latest)
|
||||||
logHome("fetchLatestEvent:response", {
|
logHome("fetchLatestEvent:response", {
|
||||||
hasLatest: Boolean(latest),
|
hasLatest: Boolean(latest),
|
||||||
@@ -243,7 +260,10 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
|
|
||||||
api
|
api
|
||||||
.onSettingChanged((change: any) => {
|
.onSettingChanged((change: any) => {
|
||||||
if (change?.key === "search_keyboard_layout" && (change?.value === "t9" || change?.value === "qwerty26")) {
|
if (
|
||||||
|
change?.key === "search_keyboard_layout" &&
|
||||||
|
(change?.value === "t9" || change?.value === "qwerty26")
|
||||||
|
) {
|
||||||
setSearchKeyboardLayout(change.value)
|
setSearchKeyboardLayout(change.value)
|
||||||
}
|
}
|
||||||
if (change?.key === "disable_search_keyboard") {
|
if (change?.key === "disable_search_keyboard") {
|
||||||
@@ -278,7 +298,9 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
setShowPinyinKeyboard(false)
|
setShowPinyinKeyboard(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
const quickCard = (target as HTMLElement | null)?.closest?.('[data-student-quick-card="true"]')
|
const quickCard = (target as HTMLElement | null)?.closest?.(
|
||||||
|
'[data-student-quick-card="true"]'
|
||||||
|
)
|
||||||
if (!quickCard) {
|
if (!quickCard) {
|
||||||
setQuickActionStudentId(null)
|
setQuickActionStudentId(null)
|
||||||
}
|
}
|
||||||
@@ -413,7 +435,8 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
})
|
})
|
||||||
case "score":
|
case "score":
|
||||||
return filtered.sort(
|
return filtered.sort(
|
||||||
(a, b) => getDisplayPoints(b) - getDisplayPoints(a) || a.name.localeCompare(b.name, "zh-CN")
|
(a, b) =>
|
||||||
|
getDisplayPoints(b) - getDisplayPoints(a) || a.name.localeCompare(b.name, "zh-CN")
|
||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
return filtered
|
return filtered
|
||||||
@@ -630,7 +653,10 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
fetchData(true)
|
fetchData(true)
|
||||||
fetchLatestEvent()
|
fetchLatestEvent()
|
||||||
emitDataUpdated("events")
|
emitDataUpdated("events")
|
||||||
logHome("performSubmit:afterSuccessRefreshDispatched", { studentCount: targetStudents.length, delta })
|
logHome("performSubmit:afterSuccessRefreshDispatched", {
|
||||||
|
studentCount: targetStudents.length,
|
||||||
|
delta,
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
messageApi.warning(
|
messageApi.warning(
|
||||||
t("home.batchPartial", { success: successCount, total: targetStudents.length })
|
t("home.batchPartial", { success: successCount, total: targetStudents.length })
|
||||||
@@ -848,7 +874,9 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
{rankBadge}
|
{rankBadge}
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: isPortraitMode ? "10px" : "12px" }}>
|
<div
|
||||||
|
style={{ display: "flex", alignItems: "center", gap: isPortraitMode ? "10px" : "12px" }}
|
||||||
|
>
|
||||||
{student.avatarUrl ? (
|
{student.avatarUrl ? (
|
||||||
<img
|
<img
|
||||||
src={student.avatarUrl}
|
src={student.avatarUrl}
|
||||||
@@ -911,40 +939,40 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
pointerEvents: isQuickActionMode ? "auto" : "none",
|
pointerEvents: isQuickActionMode ? "auto" : "none",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Button
|
<Button
|
||||||
type="primary"
|
type="primary"
|
||||||
size="small"
|
size="small"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
handleQuickAdjust(student, 1)
|
handleQuickAdjust(student, 1)
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
minWidth: "54px",
|
minWidth: "54px",
|
||||||
height: "36px",
|
height: "36px",
|
||||||
borderRadius: "18px",
|
borderRadius: "18px",
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
paddingInline: "12px",
|
paddingInline: "12px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
+1
|
+1
|
||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
danger
|
danger
|
||||||
size="small"
|
size="small"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
handleQuickAdjust(student, -1)
|
handleQuickAdjust(student, -1)
|
||||||
}}
|
}}
|
||||||
style={{
|
style={{
|
||||||
minWidth: "54px",
|
minWidth: "54px",
|
||||||
height: "36px",
|
height: "36px",
|
||||||
borderRadius: "18px",
|
borderRadius: "18px",
|
||||||
fontWeight: 700,
|
fontWeight: 700,
|
||||||
paddingInline: "12px",
|
paddingInline: "12px",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
-1
|
-1
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
style={{
|
style={{
|
||||||
@@ -984,7 +1012,9 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
}
|
}
|
||||||
style={{ fontWeight: "bold" }}
|
style={{ fontWeight: "bold" }}
|
||||||
>
|
>
|
||||||
{getDisplayPoints(student) > 0 ? `+${getDisplayPoints(student)}` : getDisplayPoints(student)}
|
{getDisplayPoints(student) > 0
|
||||||
|
? `+${getDisplayPoints(student)}`
|
||||||
|
: getDisplayPoints(student)}
|
||||||
</Tag>
|
</Tag>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1037,8 +1067,7 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
position: "relative",
|
position: "relative",
|
||||||
padding: "8px 10px",
|
padding: "8px 10px",
|
||||||
borderBottom: isLast ? "none" : "1px solid var(--ss-border-color)",
|
borderBottom: isLast ? "none" : "1px solid var(--ss-border-color)",
|
||||||
background:
|
background: isQuickActionMode || isSelected ? "rgba(22, 119, 255, 0.06)" : "transparent",
|
||||||
isQuickActionMode || isSelected ? "rgba(22, 119, 255, 0.06)" : "transparent",
|
|
||||||
transition: "background-color 160ms ease",
|
transition: "background-color 160ms ease",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@@ -1102,7 +1131,12 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
handleQuickAdjust(student, 1)
|
handleQuickAdjust(student, 1)
|
||||||
}}
|
}}
|
||||||
style={{ minWidth: "44px", height: "26px", borderRadius: "13px", paddingInline: "8px" }}
|
style={{
|
||||||
|
minWidth: "44px",
|
||||||
|
height: "26px",
|
||||||
|
borderRadius: "13px",
|
||||||
|
paddingInline: "8px",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
+1
|
+1
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1113,7 +1147,12 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
handleQuickAdjust(student, -1)
|
handleQuickAdjust(student, -1)
|
||||||
}}
|
}}
|
||||||
style={{ minWidth: "44px", height: "26px", borderRadius: "13px", paddingInline: "8px" }}
|
style={{
|
||||||
|
minWidth: "44px",
|
||||||
|
height: "26px",
|
||||||
|
borderRadius: "13px",
|
||||||
|
paddingInline: "8px",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
-1
|
-1
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1127,11 +1166,17 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
)}
|
)}
|
||||||
<Tag
|
<Tag
|
||||||
color={
|
color={
|
||||||
getDisplayPoints(student) > 0 ? "success" : getDisplayPoints(student) < 0 ? "error" : "default"
|
getDisplayPoints(student) > 0
|
||||||
|
? "success"
|
||||||
|
: getDisplayPoints(student) < 0
|
||||||
|
? "error"
|
||||||
|
: "default"
|
||||||
}
|
}
|
||||||
style={{ fontWeight: "bold", marginInlineEnd: 0 }}
|
style={{ fontWeight: "bold", marginInlineEnd: 0 }}
|
||||||
>
|
>
|
||||||
{getDisplayPoints(student) > 0 ? `+${getDisplayPoints(student)}` : getDisplayPoints(student)}
|
{getDisplayPoints(student) > 0
|
||||||
|
? `+${getDisplayPoints(student)}`
|
||||||
|
: getDisplayPoints(student)}
|
||||||
</Tag>
|
</Tag>
|
||||||
</Space>
|
</Space>
|
||||||
)}
|
)}
|
||||||
@@ -1283,7 +1328,12 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
handleQuickAdjust(student, 1)
|
handleQuickAdjust(student, 1)
|
||||||
}}
|
}}
|
||||||
style={{ minWidth: "44px", height: "28px", borderRadius: "14px", paddingInline: "8px" }}
|
style={{
|
||||||
|
minWidth: "44px",
|
||||||
|
height: "28px",
|
||||||
|
borderRadius: "14px",
|
||||||
|
paddingInline: "8px",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
+1
|
+1
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1294,7 +1344,12 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
e.stopPropagation()
|
e.stopPropagation()
|
||||||
handleQuickAdjust(student, -1)
|
handleQuickAdjust(student, -1)
|
||||||
}}
|
}}
|
||||||
style={{ minWidth: "44px", height: "28px", borderRadius: "14px", paddingInline: "8px" }}
|
style={{
|
||||||
|
minWidth: "44px",
|
||||||
|
height: "28px",
|
||||||
|
borderRadius: "14px",
|
||||||
|
paddingInline: "8px",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
-1
|
-1
|
||||||
</Button>
|
</Button>
|
||||||
@@ -1333,7 +1388,9 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
}
|
}
|
||||||
style={{ fontWeight: "bold", marginInlineEnd: 0 }}
|
style={{ fontWeight: "bold", marginInlineEnd: 0 }}
|
||||||
>
|
>
|
||||||
{getDisplayPoints(student) > 0 ? `+${getDisplayPoints(student)}` : getDisplayPoints(student)}
|
{getDisplayPoints(student) > 0
|
||||||
|
? `+${getDisplayPoints(student)}`
|
||||||
|
: getDisplayPoints(student)}
|
||||||
</Tag>
|
</Tag>
|
||||||
{isSelected && (
|
{isSelected && (
|
||||||
<Tag color="processing" style={{ marginInlineEnd: 0 }}>
|
<Tag color="processing" style={{ marginInlineEnd: 0 }}>
|
||||||
@@ -2051,35 +2108,31 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
})
|
})
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const batchToolbar = rewardMode
|
const batchToolbar = rewardMode ? null : !batchMode ? (
|
||||||
? null
|
<Button onClick={handleEnterBatchMode} disabled={!canEdit}>
|
||||||
: !batchMode
|
{t("home.multiSelect")}
|
||||||
? (
|
</Button>
|
||||||
<Button onClick={handleEnterBatchMode} disabled={!canEdit}>
|
) : (
|
||||||
{t("home.multiSelect")}
|
<Space size={8} wrap>
|
||||||
</Button>
|
<Button onClick={handleSelectAllStudents} disabled={!canEdit || students.length === 0}>
|
||||||
)
|
{t("home.selectAll")}
|
||||||
: (
|
</Button>
|
||||||
<Space size={8} wrap>
|
<Button
|
||||||
<Button onClick={handleSelectAllStudents} disabled={!canEdit || students.length === 0}>
|
onClick={handleClearSelectedStudents}
|
||||||
{t("home.selectAll")}
|
disabled={!canEdit || selectedStudentIds.length === 0}
|
||||||
</Button>
|
>
|
||||||
<Button
|
{t("home.clearSelected")}
|
||||||
onClick={handleClearSelectedStudents}
|
</Button>
|
||||||
disabled={!canEdit || selectedStudentIds.length === 0}
|
<Button
|
||||||
>
|
type="primary"
|
||||||
{t("home.clearSelected")}
|
onClick={handleOpenBatchOperation}
|
||||||
</Button>
|
disabled={!canEdit || selectedStudentIds.length === 0}
|
||||||
<Button
|
>
|
||||||
type="primary"
|
{t("home.batchOperate")}
|
||||||
onClick={handleOpenBatchOperation}
|
</Button>
|
||||||
disabled={!canEdit || selectedStudentIds.length === 0}
|
<Button onClick={handleExitBatchMode}>{t("common.cancel")}</Button>
|
||||||
>
|
</Space>
|
||||||
{t("home.batchOperate")}
|
)
|
||||||
</Button>
|
|
||||||
<Button onClick={handleExitBatchMode}>{t("common.cancel")}</Button>
|
|
||||||
</Space>
|
|
||||||
)
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
@@ -2116,7 +2169,7 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
<Space
|
<Space
|
||||||
size="middle"
|
size="middle"
|
||||||
align="start"
|
align="start"
|
||||||
wrap={isPortraitMode}
|
wrap
|
||||||
style={{
|
style={{
|
||||||
width: isPortraitMode ? "100%" : undefined,
|
width: isPortraitMode ? "100%" : undefined,
|
||||||
justifyContent: isPortraitMode ? "flex-start" : undefined,
|
justifyContent: isPortraitMode ? "flex-start" : undefined,
|
||||||
@@ -2126,8 +2179,9 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
ref={searchAreaRef}
|
ref={searchAreaRef}
|
||||||
style={{
|
style={{
|
||||||
position: "relative",
|
position: "relative",
|
||||||
width: isPortraitMode ? "100%" : "220px",
|
width: isMobile ? "100%" : isTablet ? "180px" : "220px",
|
||||||
minWidth: isPortraitMode ? "100%" : undefined,
|
minWidth: isMobile ? "100%" : isTablet ? "150px" : "180px",
|
||||||
|
flexShrink: isMobile ? 0 : 1,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Input
|
<Input
|
||||||
@@ -2193,7 +2247,11 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
: t9KeyRows.map((row, rowIndex) => (
|
: t9KeyRows.map((row, rowIndex) => (
|
||||||
<div
|
<div
|
||||||
key={`pinyin-row-${rowIndex}`}
|
key={`pinyin-row-${rowIndex}`}
|
||||||
style={{ display: "grid", gridTemplateColumns: "repeat(3, 1fr)", gap: "6px" }}
|
style={{
|
||||||
|
display: "grid",
|
||||||
|
gridTemplateColumns: "repeat(3, 1fr)",
|
||||||
|
gap: "6px",
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{row.map((keyItem) => (
|
{row.map((keyItem) => (
|
||||||
<Button
|
<Button
|
||||||
@@ -2215,7 +2273,11 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
<Select
|
<Select
|
||||||
value={sortType}
|
value={sortType}
|
||||||
onChange={(v) => setSortType(v as SortType)}
|
onChange={(v) => setSortType(v as SortType)}
|
||||||
style={{ width: isPortraitMode ? "calc(50% - 8px)" : "140px", minWidth: "120px" }}
|
style={{
|
||||||
|
width: isMobile ? "calc(50% - 8px)" : isTablet ? "130px" : "140px",
|
||||||
|
minWidth: isMobile ? "100px" : "120px",
|
||||||
|
flexShrink: isMobile ? 1 : 0,
|
||||||
|
}}
|
||||||
options={[
|
options={[
|
||||||
{ value: "alphabet", label: t("home.sortBy.alphabet") },
|
{ value: "alphabet", label: t("home.sortBy.alphabet") },
|
||||||
{ value: "surname", label: t("home.sortBy.surname") },
|
{ value: "surname", label: t("home.sortBy.surname") },
|
||||||
@@ -2225,7 +2287,11 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
<Select
|
<Select
|
||||||
value={layoutType}
|
value={layoutType}
|
||||||
onChange={(v) => setLayoutType(v as LayoutType)}
|
onChange={(v) => setLayoutType(v as LayoutType)}
|
||||||
style={{ width: isPortraitMode ? "calc(50% - 8px)" : "140px", minWidth: "120px" }}
|
style={{
|
||||||
|
width: isMobile ? "calc(50% - 8px)" : isTablet ? "130px" : "140px",
|
||||||
|
minWidth: isMobile ? "100px" : "120px",
|
||||||
|
flexShrink: isMobile ? 1 : 0,
|
||||||
|
}}
|
||||||
options={[
|
options={[
|
||||||
{ value: "grouped", label: t("home.layoutBy.grouped") },
|
{ value: "grouped", label: t("home.layoutBy.grouped") },
|
||||||
{ value: "squareGrid", label: t("home.layoutBy.squareGrid") },
|
{ value: "squareGrid", label: t("home.layoutBy.squareGrid") },
|
||||||
@@ -2244,10 +2310,20 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
})
|
})
|
||||||
: t("home.undoUnavailable")
|
: t("home.undoUnavailable")
|
||||||
}
|
}
|
||||||
|
style={{
|
||||||
|
flexShrink: isMobile ? 1 : 0,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{t("home.undoLastAction")}
|
{t("home.undoLastAction")}
|
||||||
</Button>
|
</Button>
|
||||||
<Button type={rewardMode ? "default" : "primary"} onClick={handleToggleRewardMode} disabled={!canEdit}>
|
<Button
|
||||||
|
type={rewardMode ? "default" : "primary"}
|
||||||
|
onClick={handleToggleRewardMode}
|
||||||
|
disabled={!canEdit}
|
||||||
|
style={{
|
||||||
|
flexShrink: isMobile ? 1 : 0,
|
||||||
|
}}
|
||||||
|
>
|
||||||
{rewardMode ? t("rewardExchange.exitMode") : t("rewardExchange.enterMode")}
|
{rewardMode ? t("rewardExchange.exitMode") : t("rewardExchange.enterMode")}
|
||||||
</Button>
|
</Button>
|
||||||
{batchToolbar}
|
{batchToolbar}
|
||||||
@@ -2307,7 +2383,9 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
{t("rewardExchange.currentRewardPoints", { points: rewardStudent.reward_points })}
|
{t("rewardExchange.currentRewardPoints", { points: rewardStudent.reward_points })}
|
||||||
</div>
|
</div>
|
||||||
{affordableRewards.length === 0 ? (
|
{affordableRewards.length === 0 ? (
|
||||||
<div style={{ color: "var(--ss-text-secondary)" }}>{t("rewardExchange.noAffordableRewards")}</div>
|
<div style={{ color: "var(--ss-text-secondary)" }}>
|
||||||
|
{t("rewardExchange.noAffordableRewards")}
|
||||||
|
</div>
|
||||||
) : (
|
) : (
|
||||||
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
|
<div style={{ display: "flex", flexDirection: "column", gap: 8 }}>
|
||||||
{affordableRewards.map((reward) => (
|
{affordableRewards.map((reward) => (
|
||||||
@@ -2328,7 +2406,11 @@ export const Home: React.FC<HomeProps> = ({ canEdit, isPortraitMode = false }) =
|
|||||||
{t("rewardExchange.costLabel", { points: reward.cost_points })}
|
{t("rewardExchange.costLabel", { points: reward.cost_points })}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Button type="primary" loading={redeemLoading} onClick={() => handleRedeemReward(reward)}>
|
<Button
|
||||||
|
type="primary"
|
||||||
|
loading={redeemLoading}
|
||||||
|
onClick={() => handleRedeemReward(reward)}
|
||||||
|
>
|
||||||
{t("rewardExchange.redeemNow")}
|
{t("rewardExchange.redeemNow")}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user