✨
This commit is contained in:
182
src/store/home/action.ts
Normal file
182
src/store/home/action.ts
Normal file
@@ -0,0 +1,182 @@
|
||||
import type { Action } from "../Action";
|
||||
import type {
|
||||
HomeState,
|
||||
SearchResult,
|
||||
ReplyToType,
|
||||
ProductSearchType,
|
||||
} from "./state";
|
||||
import type { Category, Reply } from "../../api/models";
|
||||
|
||||
export const SET_LOADING = "set_loading";
|
||||
export const SET_CATEGORIES = "set_categories";
|
||||
export const SET_CATEGORY_ID = "set_category_id";
|
||||
export const SET_KEYWORD = "set_keyword";
|
||||
export const SET_PAGE_INDEX = "set_page_index";
|
||||
export const SET_IS_SEARCHING = "set_is_searching";
|
||||
export const SET_SEARCH_RESULT = "set_search_result";
|
||||
export const SET_REPLIES = "set_replies";
|
||||
export const TOGGLE_ORDER_BY_PUBLISH_TIME = "toggle_order_by_publish_time";
|
||||
export const TOGGLE_ORDER_BY_CATEGORY_ID = "toggle_order_by_category_id";
|
||||
export const TOGGLE_ORDER_BY_REPLY_AMOUNT = "toggle_order_by_reply_amount";
|
||||
export const SET_IS_REPLING = "set_is_repling";
|
||||
export const SET_REPLY_TO = "set_reply_to";
|
||||
export const SET_WILL_SEARCHING = "set_will_searching";
|
||||
export const SET_SEARCH_PRODUCTS = "set_search_products";
|
||||
export const SET_SEARCH_FOCUSED = "set_search_focused";
|
||||
|
||||
export type ActionsType =
|
||||
| typeof SET_LOADING
|
||||
| typeof SET_CATEGORIES
|
||||
| typeof SET_CATEGORY_ID
|
||||
| typeof SET_KEYWORD
|
||||
| typeof SET_PAGE_INDEX
|
||||
| typeof SET_IS_SEARCHING
|
||||
| typeof SET_SEARCH_RESULT
|
||||
| typeof SET_REPLIES
|
||||
| typeof TOGGLE_ORDER_BY_PUBLISH_TIME
|
||||
| typeof TOGGLE_ORDER_BY_CATEGORY_ID
|
||||
| typeof TOGGLE_ORDER_BY_REPLY_AMOUNT
|
||||
| typeof SET_IS_REPLING
|
||||
| typeof SET_REPLY_TO
|
||||
| typeof SET_WILL_SEARCHING
|
||||
| typeof SET_SEARCH_PRODUCTS
|
||||
| typeof SET_SEARCH_FOCUSED;
|
||||
|
||||
export type HomeAction = Action<ActionsType, HomeState>;
|
||||
|
||||
export function setLoading(isLoading: boolean): HomeAction {
|
||||
return {
|
||||
type: "set_loading",
|
||||
payload: {
|
||||
isLoading,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function setCategories(categories: Array<Category>): HomeAction {
|
||||
return {
|
||||
type: "set_categories",
|
||||
payload: {
|
||||
categories,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function setCategoryId(categoryId: number): HomeAction {
|
||||
return {
|
||||
type: "set_category_id",
|
||||
payload: {
|
||||
categoryId,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function setKeyword(keyword: string): HomeAction {
|
||||
return {
|
||||
type: "set_keyword",
|
||||
payload: {
|
||||
keyword,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function setPageIndex(pageIndex: number): HomeAction {
|
||||
return {
|
||||
type: "set_page_index",
|
||||
payload: {
|
||||
pageIndex,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function setIsSearch(isSearching: boolean): HomeAction {
|
||||
return {
|
||||
type: "set_is_searching",
|
||||
payload: {
|
||||
isSearching,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function setSearchResult(result: SearchResult): HomeAction {
|
||||
return {
|
||||
type: "set_search_result",
|
||||
payload: {
|
||||
...result,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function setReplies(replies: Array<Reply> | null): HomeAction {
|
||||
return {
|
||||
type: "set_replies",
|
||||
payload: {
|
||||
replies,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function toggleOrderByPublishTime(): HomeAction {
|
||||
return {
|
||||
type: "toggle_order_by_publish_time",
|
||||
};
|
||||
}
|
||||
|
||||
export function toggleOrderByCategoryId(): HomeAction {
|
||||
return {
|
||||
type: "toggle_order_by_category_id",
|
||||
};
|
||||
}
|
||||
|
||||
export function toggleOrderByReplyAmount(): HomeAction {
|
||||
return {
|
||||
type: "toggle_order_by_reply_amount",
|
||||
};
|
||||
}
|
||||
|
||||
export function setIsRepling(isRepling: boolean): HomeAction {
|
||||
return {
|
||||
type: "set_is_repling",
|
||||
payload: {
|
||||
isRepling,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function setReplyTo(reply: Partial<ReplyToType>): HomeAction {
|
||||
return {
|
||||
type: "set_reply_to",
|
||||
payload: {
|
||||
reply,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function setWillSearching(willSearching: boolean): HomeAction {
|
||||
return {
|
||||
type: "set_will_searching",
|
||||
payload: {
|
||||
willSearching,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function setSearchProducts(
|
||||
products: Array<ProductSearchType>,
|
||||
): HomeAction {
|
||||
return {
|
||||
type: "set_search_products",
|
||||
payload: {
|
||||
products,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function setSearchFocused(searchFocused: boolean): HomeAction {
|
||||
return {
|
||||
type: "set_search_focused",
|
||||
payload: {
|
||||
searchFocused,
|
||||
},
|
||||
};
|
||||
}
|
||||
3
src/store/home/index.ts
Normal file
3
src/store/home/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
export * from "./action";
|
||||
export * from "./reducer";
|
||||
export * from "./state";
|
||||
168
src/store/home/reducer.ts
Normal file
168
src/store/home/reducer.ts
Normal file
@@ -0,0 +1,168 @@
|
||||
import type { HomeAction } from "./action";
|
||||
import type { HomeState } from "./state";
|
||||
|
||||
export const initialState: HomeState = {
|
||||
categories: [],
|
||||
isLoading: true,
|
||||
pageIndex: 1,
|
||||
categoryId: 0,
|
||||
keyword: "",
|
||||
isSearching: false,
|
||||
pageCount: 0,
|
||||
pageSize: 10,
|
||||
requests: [],
|
||||
orderBys: {
|
||||
categoryId: null,
|
||||
publishTime: "desc",
|
||||
replyAmount: null,
|
||||
},
|
||||
replies: null,
|
||||
isRepling: false,
|
||||
reply: {
|
||||
amount: 0,
|
||||
categoryId: 0,
|
||||
memo: "",
|
||||
price: 0,
|
||||
productId: 0,
|
||||
productName: "",
|
||||
requestId: 0,
|
||||
},
|
||||
searchFocused: false,
|
||||
willSearching: false,
|
||||
products: [],
|
||||
};
|
||||
|
||||
export const homeReducer = (
|
||||
state: HomeState,
|
||||
action: HomeAction,
|
||||
): HomeState => {
|
||||
switch (action.type) {
|
||||
case "set_loading": {
|
||||
return {
|
||||
...state,
|
||||
isLoading: action.payload?.isLoading || false,
|
||||
};
|
||||
}
|
||||
case "set_categories": {
|
||||
return {
|
||||
...state,
|
||||
categories: action.payload?.categories || [],
|
||||
};
|
||||
}
|
||||
case "set_category_id": {
|
||||
return {
|
||||
...state,
|
||||
categoryId: action.payload?.categoryId || 0,
|
||||
};
|
||||
}
|
||||
case "set_is_searching": {
|
||||
return {
|
||||
...state,
|
||||
isSearching: action.payload?.isSearching || false,
|
||||
};
|
||||
}
|
||||
case "set_keyword": {
|
||||
return {
|
||||
...state,
|
||||
keyword: action.payload?.keyword || "",
|
||||
};
|
||||
}
|
||||
case "set_page_index": {
|
||||
return {
|
||||
...state,
|
||||
pageIndex: action.payload?.pageIndex || 1,
|
||||
};
|
||||
}
|
||||
case "set_search_result": {
|
||||
return {
|
||||
...state,
|
||||
requests:
|
||||
state.pageIndex == 1
|
||||
? action.payload?.requests || []
|
||||
: [...state.requests, ...(action.payload?.requests || [])],
|
||||
pageCount: action.payload?.pageCount || 0,
|
||||
};
|
||||
}
|
||||
case "set_replies": {
|
||||
return {
|
||||
...state,
|
||||
isRepling: false,
|
||||
replies: action.payload?.replies || null,
|
||||
};
|
||||
}
|
||||
case "toggle_order_by_publish_time": {
|
||||
return {
|
||||
...state,
|
||||
orderBys: {
|
||||
...state.orderBys,
|
||||
publishTime:
|
||||
!state.orderBys.publishTime || state.orderBys.publishTime == "desc"
|
||||
? "asc"
|
||||
: "desc",
|
||||
},
|
||||
};
|
||||
}
|
||||
case "toggle_order_by_category_id": {
|
||||
return {
|
||||
...state,
|
||||
orderBys: {
|
||||
...state.orderBys,
|
||||
categoryId:
|
||||
!state.orderBys.categoryId || state.orderBys.categoryId == "desc"
|
||||
? "asc"
|
||||
: "desc",
|
||||
},
|
||||
};
|
||||
}
|
||||
case "toggle_order_by_reply_amount": {
|
||||
return {
|
||||
...state,
|
||||
orderBys: {
|
||||
...state.orderBys,
|
||||
replyAmount:
|
||||
!state.orderBys.replyAmount || state.orderBys.replyAmount == "desc"
|
||||
? "asc"
|
||||
: "desc",
|
||||
},
|
||||
};
|
||||
}
|
||||
case "set_is_repling": {
|
||||
return {
|
||||
...state,
|
||||
isRepling: action.payload?.isRepling ?? false,
|
||||
};
|
||||
}
|
||||
case "set_reply_to": {
|
||||
return {
|
||||
...state,
|
||||
isRepling: true,
|
||||
willSearching: false,
|
||||
reply: {
|
||||
...state.reply,
|
||||
...action.payload?.reply,
|
||||
},
|
||||
};
|
||||
}
|
||||
case "set_will_searching": {
|
||||
return {
|
||||
...state,
|
||||
willSearching: action.payload?.willSearching ?? false,
|
||||
};
|
||||
}
|
||||
case "set_search_products": {
|
||||
return {
|
||||
...state,
|
||||
willSearching: false,
|
||||
products: action.payload?.products ?? [],
|
||||
};
|
||||
}
|
||||
case "set_search_focused": {
|
||||
return {
|
||||
...state,
|
||||
searchFocused: action.payload?.searchFocused ?? false,
|
||||
};
|
||||
}
|
||||
default:
|
||||
throw Error(`未知操作(${action.type})`);
|
||||
}
|
||||
};
|
||||
65
src/store/home/state.ts
Normal file
65
src/store/home/state.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import type { Category } from "../../api/models";
|
||||
import type { Request } from "../../api/models";
|
||||
import type { Reply } from "../../api/models";
|
||||
import type { OrderByTypes } from "../Types";
|
||||
|
||||
interface OrderByState {
|
||||
publishTime: OrderByTypes;
|
||||
categoryId: OrderByTypes;
|
||||
replyAmount: OrderByTypes;
|
||||
}
|
||||
|
||||
interface SearchState {
|
||||
pageIndex: number;
|
||||
pageSize: number;
|
||||
categoryId: number;
|
||||
keyword: string;
|
||||
orderBys: OrderByState;
|
||||
isSearching: boolean;
|
||||
}
|
||||
|
||||
export interface SearchResult {
|
||||
requests: Array<Request>;
|
||||
pageCount: number;
|
||||
}
|
||||
|
||||
export interface RequestReplyState {
|
||||
replies: Array<Reply> | null;
|
||||
}
|
||||
|
||||
export interface ReplyToType {
|
||||
categoryId: number;
|
||||
requestId: number;
|
||||
productId: number;
|
||||
productName: string;
|
||||
amount: number;
|
||||
price: number;
|
||||
memo: string;
|
||||
}
|
||||
|
||||
export interface ReplyToState {
|
||||
isRepling: boolean;
|
||||
reply: Partial<ReplyToType>;
|
||||
}
|
||||
|
||||
export interface ProductSearchType {
|
||||
productId: number;
|
||||
productName: string;
|
||||
productDescription: string | null;
|
||||
price: number;
|
||||
}
|
||||
|
||||
export interface ProductSearchState {
|
||||
searchFocused: boolean;
|
||||
willSearching: boolean;
|
||||
products: Array<ProductSearchType>;
|
||||
}
|
||||
|
||||
export type HomeState = {
|
||||
categories: Array<Category>;
|
||||
isLoading: boolean;
|
||||
} & SearchState &
|
||||
SearchResult &
|
||||
RequestReplyState &
|
||||
ReplyToState &
|
||||
ProductSearchState;
|
||||
Reference in New Issue
Block a user