Skip to content

Commit

Permalink
fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
carkom committed Jan 16, 2024
1 parent b6d5178 commit 6bb0376
Show file tree
Hide file tree
Showing 10 changed files with 132 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export type Filter = {
field: string;
op: string;
value: string | number;
options: { inflow: boolean; outflow: boolean };
options: { inflow: boolean; outflow: boolean; month?: string; year?: string };
customName?: string;
};

Expand Down
15 changes: 11 additions & 4 deletions packages/desktop-client/src/components/filters/ConfigureField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ import { FocusScope } from '@react-aria/focus';

import { mapField, FIELD_TYPES, TYPE_INFO } from 'loot-core/src/shared/rules';
import { titleFirst } from 'loot-core/src/shared/util';
import {
type RuleConditionEntity,
type setOp,
} from 'loot-core/src/types/models';

import { theme } from '../../style';
import { Button } from '../common/Button';
Expand All @@ -19,10 +23,10 @@ import { subfieldToOptions } from './subfieldToOptions';
type ConfigureFieldProps = {
field: string;
initialSubfield?: string;
op: string;
op?: string;
value: string | number;
dispatch: Dispatch<{ type: string; op?: string; value?: string | number }>;
onApply: ({ field, op, value, options }) => void;
dispatch: Dispatch<RuleConditionEntity>;
onApply: (cond: RuleConditionEntity) => void;
};

export function ConfigureField({
Expand All @@ -44,6 +48,7 @@ export function ConfigureField({
// prevOp.current = op;
}, [op]);

let opTest: setOp;
const type: string | undefined = FIELD_TYPES.get(field);
let ops: Array<string> = TYPE_INFO[type].ops.filter(
(op: string) => op !== 'isbetween',
Expand Down Expand Up @@ -150,7 +155,9 @@ export function ConfigureField({
key={currOp}
op={currOp}
selected={currOp === op}
onClick={() => dispatch({ type: 'set-op', op: currOp })}
onClick={() =>
dispatch({ type: 'set-op', op: { ...opTest, currOp } })

Check failure on line 159 in packages/desktop-client/src/components/filters/ConfigureField.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Spread types may only be created from object types.

Check failure on line 159 in packages/desktop-client/src/components/filters/ConfigureField.tsx

View workflow job for this annotation

GitHub Actions / typecheck

Spread types may only be created from object types.
}
/>
))}
</Stack>
Expand Down
34 changes: 24 additions & 10 deletions packages/desktop-client/src/components/filters/FilterButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,10 @@ import {
TYPE_INFO,
} from 'loot-core/src/shared/rules';
import { titleFirst } from 'loot-core/src/shared/util';
import {
type TransactionFilterEntity,
type RuleConditionEntity,
} from 'loot-core/src/types/models';

import { theme } from '../../style';
import { HoverTarget } from '../common/HoverTarget';
Expand All @@ -27,6 +31,7 @@ import { Text } from '../common/Text';
import { View } from '../common/View';
import { Tooltip } from '../tooltips';

import { type Filter } from './AppliedFilters';
import { CompactFiltersButton } from './CompactFiltersButton';
import { ConfigureField } from './ConfigureField';
import { FiltersButton } from './FiltersButton';
Expand All @@ -51,29 +56,29 @@ type FilterButtonProps = {
};

export function FilterButton({ onApply, compact, hover }: FilterButtonProps) {
const filters = useFilters();
const filters: Filter[] | TransactionFilterEntity[] = useFilters();

const { dateFormat } = useSelector((state: any) => {
const { dateFormat } = useSelector((state: { prefs: any }) => {

Check warning on line 61 in packages/desktop-client/src/components/filters/FilterButton.tsx

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 61 in packages/desktop-client/src/components/filters/FilterButton.tsx

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
return {
dateFormat: state.prefs.local.dateFormat ?? 'MM/dd/yyyy',
};
});

const [state, dispatch] = useReducer(
(state: any, action: any) => {
(state: object, action: RuleConditionEntity) => {
switch (action.type) {
case 'select-field':
return { ...state, fieldsOpen: true, condOpen: false };
case 'configure': {
const { field } = deserializeField(action.field);
const type: string | undefined = FIELD_TYPES.get(field);
const info: any = TYPE_INFO.find(f => f.name === type);
const info: string = TYPE_INFO.find(f => f.name === type).ops[0];
return {
...state,
fieldsOpen: false,
condOpen: true,
field: action.field,
op: info.ops[0],
op: info,
value: type === 'boolean' ? true : null,
};
}
Expand All @@ -86,13 +91,22 @@ export function FilterButton({ onApply, compact, hover }: FilterButtonProps) {
{ fieldsOpen: false, condOpen: false, field: null, value: null },
);

async function onValidateAndApply(cond: any) {
cond = unparse({ ...cond, type: FIELD_TYPES.get(cond.field) });
async function onValidateAndApply(cond: RuleConditionEntity) {
const valueIsString: string = typeof cond.value === 'string' && cond.value;
const saveItem: RuleConditionEntity = {
...cond,
type: FIELD_TYPES.get(cond.field),
};
cond = unparse({ item: saveItem });

if (cond.type === 'date' && cond.options) {
if (
cond.type === 'date' &&
typeof cond.value !== 'number' &&
cond.options
) {
if (cond.options.month) {
const date = parseDate(
cond.value,
valueIsString,
getMonthYearFormat(dateFormat),
new Date(),
);
Expand All @@ -103,7 +117,7 @@ export function FilterButton({ onApply, compact, hover }: FilterButtonProps) {
return;
}
} else if (cond.options.year) {
const date = parseDate(cond.value, 'yyyy', new Date());
const date = parseDate(valueIsString, 'yyyy', new Date());
if (isDateValid(date)) {
cond.value = formatDate(date, 'yyyy');
} else {
Expand Down
14 changes: 10 additions & 4 deletions packages/desktop-client/src/components/filters/FilterEditor.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import React, { useReducer } from 'react';

import { unparse, FIELD_TYPES } from 'loot-core/src/shared/rules';
import { type RuleConditionEntity } from 'loot-core/src/types/models';

import { type Filter } from './AppliedFilters';
import { ConfigureField } from './ConfigureField';
import { subfieldFromFilter } from './subfieldFromFilter';
import { updateFilterReducer } from './updateFilterReducer';
Expand All @@ -11,7 +13,7 @@ type FilterEditorProps = {
op: string;
value: string | number;
options: { inflow: boolean; outflow: boolean };
onSave: ({field, op, value, options}) => void;
onSave: (cond: RuleConditionEntity) => Filter;
onClose: () => void;
};

Expand All @@ -24,7 +26,7 @@ export function FilterEditor({
onClose,
}: FilterEditorProps) {
const [state, dispatch] = useReducer(
(state: any, action: any) => {
(state: any, action: RuleConditionEntity) => {

Check warning on line 29 in packages/desktop-client/src/components/filters/FilterEditor.tsx

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 29 in packages/desktop-client/src/components/filters/FilterEditor.tsx

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
switch (action.type) {
case 'close':
onClose();
Expand All @@ -43,8 +45,12 @@ export function FilterEditor({
op={state.op}
value={state.value}
dispatch={dispatch}
onApply={cond => {
cond = unparse({ ...cond, type: FIELD_TYPES.get(cond.field) });
onApply={(cond: RuleConditionEntity) => {
const saveItem: RuleConditionEntity = {
...cond,
type: FIELD_TYPES.get(cond.field),
};
cond = unparse({ item: saveItem });
onSave(cond);
onClose();
}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState } from 'react';

import { mapField, friendlyOp } from 'loot-core/src/shared/rules';
import { integerToCurrency } from 'loot-core/src/shared/util';
import { type RuleConditionEntity } from 'loot-core/src/types/models';

import { SvgDelete } from '../../icons/v0';
import { type CSSProperties, theme } from '../../style';
Expand All @@ -10,6 +11,7 @@ import { Text } from '../common/Text';
import { View } from '../common/View';
import { Value } from '../rules/Value';

import { type Filter } from './AppliedFilters';
import { FilterEditor } from './FilterEditor';
import { subfieldFromFilter } from './subfieldFromFilter';

Expand All @@ -18,9 +20,9 @@ type FilterExpressionProps = {
customName: string;
op: string;
value: string | number;
options: { inflow: any; outflow: any };
options: RuleConditionEntity['options'];
style?: CSSProperties;
onChange: (newFilter: any) => void;
onChange: (cond: RuleConditionEntity) => Filter;
onDelete: () => void;
};

Expand Down
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
type subfieldFromFilterProps = {
field: string;
value: string | number;
options?: { inflow: any; outflow: any };
};
import { type RuleConditionEntity } from 'loot-core/src/types/models';

export function subfieldFromFilter({
field,
options,
value,
}: subfieldFromFilterProps) {
}: RuleConditionEntity) {
if (typeof value === 'number') {
return field;
} else if (field === 'date') {
if (value.length === 7) {
return 'month';
} else if (value.length === 4) {
return 'year';
}
} else if (field === 'amount') {
if (options && options.inflow) {
return 'amount-inflow';
} else if (options && options.outflow) {
return 'amount-outflow';
} else if (value === 'string') {
if (field === 'date') {
if (value.length === 7) {
return 'month';
} else if (value.length === 4) {
return 'year';
}
} else if (field === 'amount') {
if (options && options.inflow) {
return 'amount-inflow';
} else if (options && options.outflow) {
return 'amount-outflow';
}
}
}
return field;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,34 @@
import { type RuleConditionEntity } from 'loot-core/src/types/models';

export function subfieldToOptions(field: string, subfield: string) {
let setOptions: RuleConditionEntity['options'];
switch (field) {
case 'amount':
switch (subfield) {
case 'amount-inflow':
return { inflow: true };
setOptions = { ...setOptions, inflow: true };
break;
case 'amount-outflow':
return { outflow: true };
setOptions = { ...setOptions, outflow: true };
break;
default:
return null;
break;
}
break;
case 'date':
switch (subfield) {
case 'month':
return { month: true };
setOptions = { ...setOptions, month: true };
break;
case 'year':
return { year: true };
setOptions = { ...setOptions, year: true };
break;
default:
return null;
break;
}
break;
default:
return null;
break;
}
return setOptions;
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { makeValue, FIELD_TYPES } from 'loot-core/src/shared/rules';
import { type RuleConditionEntity } from 'loot-core/src/types/models';

export function updateFilterReducer(state: any, action: any) {
export function updateFilterReducer(state: any, action: RuleConditionEntity) {

Check warning on line 4 in packages/desktop-client/src/components/filters/updateFilterReducer.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type

Check warning on line 4 in packages/desktop-client/src/components/filters/updateFilterReducer.ts

View workflow job for this annotation

GitHub Actions / lint

Unexpected any. Specify a different type
switch (action.type) {
case 'set-op': {
const type = FIELD_TYPES.get(state.field);
Expand Down
31 changes: 24 additions & 7 deletions packages/loot-core/src/shared/rules.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
// @ts-strict-ignore
import { RuleConditionEntity } from '../types/models';

import { integerToAmount, amountToInteger, currencyToAmount } from './util';

// For now, this info is duplicated from the backend. Figure out how
Expand Down Expand Up @@ -195,28 +197,43 @@ export function parse(item) {
return { ...item, error: null };
}

export function unparse({ error, inputKey, ...item }) {
export function unparse({
item,
error,
inputKey,
}: {
item: RuleConditionEntity;
error?: string;
inputKey?: string;
}) {
let saveItem: RuleConditionEntity = item;
switch (item.type) {
case 'number': {
let unparsed = item.value;
if (item.field === 'amount' && item.op !== 'isbetween') {
if (
item.field === 'amount' &&
item.op !== 'isbetween' &&
typeof unparsed === 'number'
) {
unparsed = amountToInteger(unparsed);
}

return { ...item, value: unparsed };
saveItem = { ...item, value: unparsed };
break;
}
case 'string': {
const unparsed = item.value == null ? '' : item.value;
return { ...item, value: unparsed };
saveItem = { ...item, value: unparsed };
break;
}
case 'boolean': {
const unparsed = item.value == null ? false : item.value;
return { ...item, value: unparsed };
saveItem = { ...item, value: unparsed };
break;
}
default:
}

return item;
return saveItem;
}

export function makeValue(value, cond) {
Expand Down
Loading

0 comments on commit 6bb0376

Please sign in to comment.