import { memo, useCallback, useEffect, useState } from "react"; import { memoService, shortcutService } from "../services"; import { checkShouldShowMemoWithFilters, filterConsts, getDefaultFilter, relationConsts } from "../helpers/filter"; import useLoading from "../hooks/useLoading"; import Icon from "./Icon"; import { generateDialog } from "./Dialog"; import toastHelper from "./Toast"; import Selector from "./common/Selector"; import "../less/create-shortcut-dialog.less"; interface Props extends DialogProps { shortcutId?: ShortcutId; } const CreateShortcutDialog: React.FC = (props: Props) => { const { destroy, shortcutId } = props; const [title, setTitle] = useState(""); const [filters, setFilters] = useState([]); const requestState = useLoading(false); const shownMemoLength = memoService.getState().memos.filter((memo) => { return checkShouldShowMemoWithFilters(memo, filters); }).length; useEffect(() => { if (shortcutId) { const shortcutTemp = shortcutService.getShortcutById(shortcutId); if (shortcutTemp) { setTitle(shortcutTemp.title); const temp = JSON.parse(shortcutTemp.payload); if (Array.isArray(temp)) { setFilters(temp); } } } }, [shortcutId]); const handleTitleInputChange = (e: React.ChangeEvent) => { const text = e.target.value as string; setTitle(text); }; const handleSaveBtnClick = async () => { if (!title) { toastHelper.error("Title is required"); return; } try { if (shortcutId) { await shortcutService.patchShortcut({ id: shortcutId, title, payload: JSON.stringify(filters), }); } else { await shortcutService.createShortcut({ title, payload: JSON.stringify(filters), }); } } catch (error: any) { toastHelper.error(error.message); } destroy(); }; const handleAddFilterBenClick = () => { if (filters.length > 0) { const lastFilter = filters[filters.length - 1]; if (lastFilter.value.value === "") { toastHelper.info("Please fill in previous filter value"); return; } } setFilters([...filters, getDefaultFilter()]); }; const handleFilterChange = useCallback((index: number, filter: Filter) => { setFilters((filters) => { const temp = [...filters]; temp[index] = filter; return temp; }); }, []); const handleFilterRemove = useCallback((index: number) => { setFilters((filters) => { const temp = filters.filter((_, i) => i !== index); return temp; }); }, []); return ( <>

🚀 {shortcutId ? "Edit Shortcut" : "Create Shortcut"}

Title
Filters
{filters.map((f, index) => { return ( ); })}
New Filter
{shownMemoLength} eligible memo
); }; interface MemoFilterInputerProps { index: number; filter: Filter; handleFilterChange: (index: number, filter: Filter) => void; handleFilterRemove: (index: number) => void; } const FilterInputer: React.FC = (props: MemoFilterInputerProps) => { const { index, filter, handleFilterChange, handleFilterRemove } = props; const tags = Array.from(memoService.getState().tags); const { type } = filter; const [inputElements, setInputElements] = useState(<>); useEffect(() => { let operatorElement = <>; if (Object.keys(filterConsts).includes(type)) { operatorElement = ( ); } let valueElement = <>; switch (type) { case "TYPE": { valueElement = ( ); break; } case "TAG": { valueElement = ( { return { text: t, value: t }; })} value={filter.value.value} handleValueChanged={handleValueChange} /> ); break; } case "TEXT": { valueElement = ( { handleValueChange(event.target.value); event.target.focus(); }} /> ); break; } } setInputElements( <> {operatorElement} {valueElement} ); }, [type, filter]); const handleRelationChange = useCallback( (value: string) => { if (["AND", "OR"].includes(value)) { handleFilterChange(index, { ...filter, relation: value as MemoFilterRalation, }); } }, [filter] ); const handleTypeChange = useCallback( (value: string) => { if (filter.type !== value) { const ops = Object.values(filterConsts[value as FilterType].operators); handleFilterChange(index, { ...filter, type: value as FilterType, value: { operator: ops[0].value, value: "", }, }); } }, [filter] ); const handleOperatorChange = useCallback( (value: string) => { handleFilterChange(index, { ...filter, value: { ...filter.value, operator: value, }, }); }, [filter] ); const handleValueChange = useCallback( (value: string) => { handleFilterChange(index, { ...filter, value: { ...filter.value, value, }, }); }, [filter] ); const handleRemoveBtnClick = () => { handleFilterRemove(index); }; return (
{index > 0 ? ( ) : null} {inputElements}
); }; const MemoFilterInputer: React.FC = memo(FilterInputer); export default function showCreateShortcutDialog(shortcutId?: ShortcutId): void { generateDialog( { className: "create-shortcut-dialog", }, CreateShortcutDialog, { shortcutId } ); }