This commit is contained in:
2026-05-20 15:40:17 +07:00
parent 230eb9010c
commit dd3fd889a3
48 changed files with 3374 additions and 737 deletions

View File

@@ -1,5 +1,4 @@
import type { Place } from "./types";
import { PLACES } from "./mock-data";
export type Screen = "places" | "collections" | "profile" | "place" | "collection";
@@ -7,16 +6,20 @@ export type Tab = "places" | "collections" | "profile";
export type StackFrame = {
screen: Screen;
placeId?: string;
collectionId?: string;
placeId?: number;
collectionId?: number;
};
export type Modal =
| { type: "add" }
| { type: "invite"; collectionId: string }
| { type: "members"; collectionId: string }
| { type: "confirmDeletePlace"; placeId: string }
| { type: "confirmDeleteCollection"; collectionId: string }
| { type: "editPlace"; placeId: number }
| { type: "saveToCollection"; placeId: number }
| { type: "createCollection" }
| { type: "editCollection"; collectionId: number }
| { type: "invite"; collectionId: number }
| { type: "members"; collectionId: number }
| { type: "confirmDeletePlace"; placeId: number }
| { type: "confirmDeleteCollection"; collectionId: number }
| null;
export type AppState = {
@@ -32,37 +35,43 @@ export type AppState = {
};
export type Action =
| { type: "NAV"; screen: Screen; placeId?: string; collectionId?: string }
| { type: "NAV"; screen: Screen; placeId?: number; collectionId?: number }
| { type: "BACK" }
| { type: "TAB"; tab: Tab }
| { type: "SET_FILTER"; value: string }
| { type: "SET_SEARCH"; value: string }
| { type: "TOGGLE_VISITED"; placeId: string }
| { type: "SET_RATING"; placeId: string; value: number }
| { type: "SET_NOTES"; placeId: string; value: string }
| { type: "TOGGLE_VISITED"; placeId: number }
| { type: "SET_RATING"; placeId: number; value: number }
| { type: "SET_NOTES"; placeId: number; value: string }
| { type: "ADD_PLACE"; place: Place }
| { type: "DELETE_PLACE"; placeId: string }
| { type: "DELETE_PLACE"; placeId: number }
| { type: "TOAST"; value: string }
| { type: "CLEAR_TOAST"; key: number }
| { type: "OPEN_ADD" }
| { type: "OPEN_INVITE"; collectionId: string }
| { type: "OPEN_MEMBERS"; collectionId: string }
| { type: "CONFIRM_DELETE_PLACE"; placeId: string }
| { type: "CONFIRM_DELETE_COLLECTION"; collectionId: string }
| { type: "OPEN_EDIT_PLACE"; placeId: number }
| { type: "OPEN_SAVE_TO_COLLECTION"; placeId: number }
| { type: "OPEN_CREATE_COLLECTION" }
| { type: "OPEN_EDIT_COLLECTION"; collectionId: number }
| { type: "OPEN_INVITE"; collectionId: number }
| { type: "OPEN_MEMBERS"; collectionId: number }
| { type: "CONFIRM_DELETE_PLACE"; placeId: number }
| { type: "CONFIRM_DELETE_COLLECTION"; collectionId: number }
| { type: "CLOSE_MODAL" }
| { type: "SET_OFFLINE"; value: boolean };
export const INITIAL_STATE: AppState = {
tab: "places",
stack: [{ screen: "places" }],
filter: "all",
search: "",
places: PLACES,
modal: null,
toast: null,
toastKey: 0,
offline: false,
};
export function makeInitialState(places: Place[]): AppState {
return {
tab: "places",
stack: [{ screen: "places" }],
filter: "all",
search: "",
places,
modal: null,
toast: null,
toastKey: 0,
offline: false,
};
}
export function reducer(state: AppState, action: Action): AppState {
switch (action.type) {
@@ -77,9 +86,8 @@ export function reducer(state: AppState, action: Action): AppState {
if (state.stack.length <= 1) return state;
return { ...state, stack: state.stack.slice(0, -1) };
}
case "TAB": {
case "TAB":
return { ...state, tab: action.tab, stack: [{ screen: action.tab }] };
}
case "SET_FILTER":
return { ...state, filter: action.value };
case "SET_SEARCH":
@@ -112,23 +120,29 @@ export function reducer(state: AppState, action: Action): AppState {
);
return { ...state, places };
}
case "ADD_PLACE": {
case "ADD_PLACE":
return { ...state, places: [action.place, ...state.places] };
}
case "DELETE_PLACE": {
case "DELETE_PLACE":
return {
...state,
places: state.places.filter((p) => p.id !== action.placeId),
stack: state.stack.length > 1 ? state.stack.slice(0, -1) : state.stack,
modal: null,
};
}
case "TOAST":
return { ...state, toast: action.value, toastKey: state.toastKey + 1 };
case "CLEAR_TOAST":
return state.toastKey === action.key ? { ...state, toast: null } : state;
case "OPEN_ADD":
return { ...state, modal: { type: "add" } };
case "OPEN_EDIT_PLACE":
return { ...state, modal: { type: "editPlace", placeId: action.placeId } };
case "OPEN_SAVE_TO_COLLECTION":
return { ...state, modal: { type: "saveToCollection", placeId: action.placeId } };
case "OPEN_CREATE_COLLECTION":
return { ...state, modal: { type: "createCollection" } };
case "OPEN_EDIT_COLLECTION":
return { ...state, modal: { type: "editCollection", collectionId: action.collectionId } };
case "OPEN_INVITE":
return { ...state, modal: { type: "invite", collectionId: action.collectionId } };
case "OPEN_MEMBERS":