Commit 760de93a authored by timel's avatar timel

feat: support change order

parent 07bd9ee3
Pipeline #23032 failed with stages
in 13 minutes and 44 seconds
import { InfoCircleFilled } from "@ant-design/icons";
import {
Button,
Checkbox,
Form,
Input,
InputNumber,
type InputNumberProps,
Select,
type SelectProps,
type InputNumberProps,
Tooltip,
} from "antd";
import {
CheckOutlined,
DeleteOutlined,
EditOutlined,
FilterOutlined,
SearchOutlined,
SortAscendingOutlined,
UndoOutlined,
InfoCircleFilled,
} from "@ant-design/icons";
import { useState } from "react";
import { fetchStrings, Region } from "@/api";
......@@ -58,7 +46,7 @@ export const Filter: React.FC<{
mode="multiple"
allowClear
style={{ width: "100%" }}
placeholder="Please select"
placeholder="请选择"
options={Array.from(Attribute2StringCodeMap.entries()).map(
([key, value]) => ({
value: key,
......@@ -81,7 +69,7 @@ export const Filter: React.FC<{
mode="multiple"
allowClear
style={{ width: "100%" }}
placeholder="Please select"
placeholder="请选择"
options={levels.map((level) => ({
value: level,
label: level.toString(),
......@@ -102,7 +90,7 @@ export const Filter: React.FC<{
mode="multiple"
allowClear
style={{ width: "100%" }}
placeholder="Please select"
placeholder="请选择"
options={Array.from(Race2StringCodeMap.entries()).map(
([key, value]) => ({
value: key,
......@@ -125,7 +113,7 @@ export const Filter: React.FC<{
mode="multiple"
allowClear
style={{ width: "100%" }}
placeholder="Please select"
placeholder="请选择"
options={Array.from(Type2StringCodeMap.entries()).map(
([key, value]) => ({
value: key,
......
import { proxy } from "valtio";
import { type CardMeta } from "@/api";
import { compareCards, type EditingDeck, type Type } from "./utils";
export const editDeckStore = proxy({
deckName: "",
main: [] as CardMeta[],
extra: [] as CardMeta[],
side: [] as CardMeta[],
add(type: Type, card: CardMeta) {
editDeckStore[type].push(card);
editDeckStore[type].sort(compareCards);
editDeckStore.edited = true;
},
remove(type: Type, card: CardMeta) {
const index = editDeckStore[type].findIndex((item) => item.id === card.id);
if (index !== -1) {
editDeckStore[type].splice(index, 1);
editDeckStore.edited = true;
}
},
set(deck: EditingDeck) {
editDeckStore.deckName = deck.deckName;
editDeckStore.main = deck.main.sort(compareCards);
editDeckStore.extra = deck.extra.sort(compareCards);
editDeckStore.side = deck.side.sort(compareCards);
editDeckStore.edited = false;
},
clear() {
editDeckStore.main = [];
editDeckStore.extra = [];
editDeckStore.side = [];
editDeckStore.edited = true;
},
edited: false,
}) satisfies EditingDeck;
......@@ -12,11 +12,11 @@ import {
Badge,
Button,
ConfigProvider,
Dropdown,
Input,
type MenuProps,
Space,
type ThemeConfig,
Dropdown,
type MenuProps,
} from "antd";
import classNames from "classnames";
import { memo, useEffect, useRef, useState } from "react";
......@@ -24,7 +24,7 @@ import { DndProvider, useDrag, useDrop } from "react-dnd";
import { HTML5Backend } from "react-dnd-html5-backend";
import { LoaderFunction } from "react-router-dom";
import { v4 as v4uuid } from "uuid";
import { proxy, useSnapshot } from "valtio";
import { useSnapshot } from "valtio";
import { subscribeKey } from "valtio/utils";
import { type CardMeta, searchCards } from "@/api";
......@@ -41,12 +41,11 @@ import {
import { CardDetail } from "./CardDetail";
import { DeckSelect } from "./DeckSelect";
import { editDeckStore } from "./editDeckStore";
import { Filter } from "./Filter";
import styles from "./index.module.scss";
import {
canAdd,
compareCards,
type EditingDeck,
editingDeckToIDeck,
iDeckToEditingDeck,
type Type,
......@@ -60,42 +59,6 @@ const theme: ThemeConfig = {
},
};
const items: MenuProps["items"] = [
{
key: "5",
label: "从新到旧",
},
{
key: "6",
label: "从旧到新",
},
{
key: "1",
label: "攻击力从高到低",
},
{
key: "2",
label: "攻击力从低到高",
},
{
key: "3",
label: "守备力从高到低",
},
{
key: "4",
label: "守备力从低到高",
},
{
key: "7",
label: "星/阶/刻/Link从高到低",
},
{
key: "8",
label: "星/阶/刻/Link从低到高",
},
];
export const loader: LoaderFunction = async () => {
// 必须先加载卡组,不然页面会崩溃
if (!initStore.decks) {
......@@ -111,7 +74,7 @@ export const Component: React.FC = () => {
const { sqlite } = useSnapshot(initStore);
const [selectedDeck, setSelectedDeck] = useState<IDeck>(deckStore.decks[0]);
const { message, notification, modal } = App.useApp();
const { message } = App.useApp();
const handleDeckEditorReset = async () => {
editDeckStore.set(await iDeckToEditingDeck(selectedDeck));
......@@ -247,11 +210,53 @@ const Search: React.FC = () => {
const [searchWord, setSearchWord] = useState("");
const [searchConditions, setSearchConditions] = useState<FtsConditions>({});
const [searchResult, setSearchResult] = useState<CardMeta[]>([]);
const [filterOpen, setFilterOpen] = useState(false);
const sortRef = useRef<(a: CardMeta, b: CardMeta) => number>(
(a: CardMeta, b: CardMeta) => a.id - b.id
);
const setSortRef = (sort: (a: CardMeta, b: CardMeta) => number) => {
sortRef.current = sort;
setSearchResult([...searchResult.sort(sortRef.current)]);
};
const dropdownOptions: MenuProps["items"] = (
[
["从新到旧", () => setSortRef((a, b) => b.id - a.id)],
["从旧到新", () => setSortRef((a, b) => a.id - b.id)],
[
"攻击力从高到低",
() => setSortRef((a, b) => (b.data?.atk ?? 0) - (a.data?.atk ?? 0)),
],
[
"攻击力从低到高",
() => setSortRef((a, b) => (a.data?.atk ?? 0) - (b.data?.atk ?? 0)),
],
[
"守备力从高到低",
() => setSortRef((a, b) => (b.data?.def ?? 0) - (a.data?.def ?? 0)),
],
[
"守备力从低到高",
() => setSortRef((a, b) => (a.data?.def ?? 0) - (b.data?.def ?? 0)),
],
[
"星/阶/刻/Link从高到低",
() => setSortRef((a, b) => (a.data?.level ?? 0) - (b.data?.level ?? 0)),
],
[
"星/阶/刻/Link从低到高",
() => setSortRef((a, b) => (b.data?.level ?? 0) - (a.data?.level ?? 0)),
],
] as const
).map(([label, onClick], key) => ({ key, label, onClick }));
const handleSearch = async () => {
const result = (
await searchCards({ query: searchWord, conditions: searchConditions })
).filter((card) => !isToken(card.data.type ?? 0)); // 衍生物不显示
)
.filter((card) => !isToken(card.data.type ?? 0))
.sort(sortRef.current); // 衍生物不显示
setSearchResult(result);
};
......@@ -314,8 +319,7 @@ const Search: React.FC = () => {
{false && <Badge dot offset={[5, -5]} />}
</Button>
<Dropdown
overlayStyle={{ backdropFilter: "blur(10px)" }}
menu={{ items }}
menu={{ items: dropdownOptions }}
trigger={["click"]}
placement="bottom"
arrow
......@@ -389,12 +393,12 @@ const DeckZone: React.FC<{
ref={dropRef}
>
<div className={styles["card-continer"]}>
{cards.map((item, i) => (
{cards.map((card) => (
<Card
value={item}
key={i}
value={card}
key={v4uuid()}
source={type}
onRightClick={() => editDeckStore.remove(type, item)}
onRightClick={() => editDeckStore.remove(type, card)}
/>
))}
<div className={styles["editing-zone-name"]}>{type.toUpperCase()}</div>
......@@ -416,7 +420,7 @@ const SearchResults: React.FC<{
{results.map((card) => (
<Card
value={card}
key={v4uuid()}
key={card.id}
source="search"
onClick={() => handleClick(card)}
/>
......@@ -457,36 +461,3 @@ const Card: React.FC<{
</div>
);
});
const editDeckStore = proxy({
deckName: "",
main: [] as CardMeta[],
extra: [] as CardMeta[],
side: [] as CardMeta[],
add(type: Type, card: CardMeta) {
editDeckStore[type].push(card);
editDeckStore[type].sort(compareCards);
editDeckStore.edited = true;
},
remove(type: Type, card: CardMeta) {
const index = editDeckStore[type].findIndex((item) => item.id === card.id);
if (index !== -1) {
editDeckStore[type].splice(index, 1);
editDeckStore.edited = true;
}
},
set(deck: EditingDeck) {
editDeckStore.deckName = deck.deckName;
editDeckStore.main = deck.main.sort(compareCards);
editDeckStore.extra = deck.extra.sort(compareCards);
editDeckStore.side = deck.side.sort(compareCards);
editDeckStore.edited = false;
},
clear() {
editDeckStore.main = [];
editDeckStore.extra = [];
editDeckStore.side = [];
editDeckStore.edited = true;
},
edited: false,
}) satisfies EditingDeck;
......@@ -30,7 +30,9 @@ export const theme: ThemeConfig = {
colorBgContainer: "hsla(0, 0%, 100%, 0.05)",
},
Dropdown: {
colorBgElevated: "hsla(0, 0%, 100%, 0.15)",
colorBgElevated: "#3f4d60",
boxShadow:
"0 6px 16px 0 rgb(51 51 51 / 80%), 0 3px 6px -4px rgba(0, 0, 0, 0.12), 0 9px 28px 8px rgba(0, 0, 0, 0.05)",
},
},
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment