<commit_before>import { findIndex } from "lodash";
import { SagaIterator } from "redux-saga";
import { call, put, select } from "redux-saga/effects";

import { extractTagsFromTasks, INewTask, ITask, tasksRepository } from "../lib/tasks";
import createItemsDuck, { IState as IItemsState, Reducer } from "./items";
import { takeEvery } from "./utils";

export interface IState extends IItemsState<ITask> {
    creatingItem: boolean;
    currentTag: string | null;
    tags: string[];
}

const duck = createItemsDuck(
    "tasks",
    tasksRepository,
    (task: INewTask) => ({
        ...task,
        createdAt: Date.now(),
        spentSeconds: 0,
        updatedAt: Date.now(),
    }),
    {
        onToggleTaskState: (task: ITask): ITask => ({ ...task, updatedAt: Date.now() }),
        partialInitialState: {
            creatingItem: false,
            currentTag: null,
            tags: [],
        },
    },
);

const factory = duck.actionCreatorFactory;

const getTags = factory.async<void, string[]>("GET_TAGS");
const setCurrentTag = factory<string | null>("SET_CURRENT_TAG");
const startCreatingItem = factory("START_CREATING_TASK");
const stopCreatingItem = factory("STOP_CREATING_TASK");
const updateCurrentItem = factory<ITask>("UPDATE_CURRENT_TASK");

export const actionCreators = {
    ...duck.actionCreators,
    getTags: () => getTags.started(null),
    setCurrentTag,
    startCreatingItem,
    stopCreatingItem,
    updateCurrentItem,
};

export const initialState = duck.initialState;

export const reducer =
    (duck.reducer as Reducer<ITask, IState>)
        .case(duck.actionCreators.createItem, (state) => state.merge({ creatingItem: false }))
        .case(getTags.done, (state, { result }) => state.merge({ tags: result }))
        .case(setCurrentTag, (state, currentTag) => state.merge({ currentTag }))
        .case(startCreatingItem, (state) => state.merge({ creatingItem: true }))
        .case(stopCreatingItem, (state) => state.merge({ creatingItem: false }));

export const sagas = [
    ...duck.sagas,
    takeEvery(
        getTags.started,
        function* _(): SagaIterator {
            yield put(getTags.done({
                params: null,
                result: extractTagsFromTasks([
                    ...(yield call(tasksRepository(false).get)),
                    ...(yield call(tasksRepository(true).get)),
                ]),
            }));
        }),
    takeEvery(
        updateCurrentItem,
        function* _(task: ITask): SagaIterator {
            task = { ...task, updatedAt: Date.now() };

            const state = yield duck.selectState();
            const items = [...state.items];

            items[findIndex(items, state.currentItem)] = task;

            yield put(actionCreators.setItems(items));
            yield put(actionCreators.setCurrentItem(task));
            yield put(getTags.started(null));
        }),
];
<commit_msg>Nullify current tag after creating tasks<commit_after>import { findIndex } from "lodash";
import { SagaIterator } from "redux-saga";
import { call, put, select } from "redux-saga/effects";

import { extractTagsFromTasks, INewTask, ITask, tasksRepository } from "../lib/tasks";
import createItemsDuck, { IState as IItemsState, Reducer } from "./items";
import { takeEvery } from "./utils";

export interface IState extends IItemsState<ITask> {
    creatingItem: boolean;
    currentTag: string | null;
    tags: string[];
}

const duck = createItemsDuck(
    "tasks",
    tasksRepository,
    (task: INewTask) => ({
        ...task,
        createdAt: Date.now(),
        spentSeconds: 0,
        updatedAt: Date.now(),
    }),
    {
        onToggleTaskState: (task: ITask): ITask => ({ ...task, updatedAt: Date.now() }),
        partialInitialState: {
            creatingItem: false,
            currentTag: null,
            tags: [],
        },
    },
);

const factory = duck.actionCreatorFactory;

const getTags = factory.async<void, string[]>("GET_TAGS");
const setCurrentTag = factory<string | null>("SET_CURRENT_TAG");
const startCreatingItem = factory("START_CREATING_TASK");
const stopCreatingItem = factory("STOP_CREATING_TASK");
const updateCurrentItem = factory<ITask>("UPDATE_CURRENT_TASK");

export const actionCreators = {
    ...duck.actionCreators,
    getTags: () => getTags.started(null),
    setCurrentTag,
    startCreatingItem,
    stopCreatingItem,
    updateCurrentItem,
};

export const initialState = duck.initialState;

export const reducer =
    (duck.reducer as Reducer<ITask, IState>)
        .case(duck.actionCreators.createItem, (state) =>
            state.merge({ creatingItem: false, currentTag: null }))
        .case(getTags.done, (state, { result }) => state.merge({ tags: result }))
        .case(setCurrentTag, (state, currentTag) => state.merge({ currentTag }))
        .case(startCreatingItem, (state) => state.merge({ creatingItem: true }))
        .case(stopCreatingItem, (state) => state.merge({ creatingItem: false }));

export const sagas = [
    ...duck.sagas,
    takeEvery(
        getTags.started,
        function* _(): SagaIterator {
            yield put(getTags.done({
                params: null,
                result: extractTagsFromTasks([
                    ...(yield call(tasksRepository(false).get)),
                    ...(yield call(tasksRepository(true).get)),
                ]),
            }));
        }),
    takeEvery(
        updateCurrentItem,
        function* _(task: ITask): SagaIterator {
            task = { ...task, updatedAt: Date.now() };

            const state = yield duck.selectState();
            const items = [...state.items];

            items[findIndex(items, state.currentItem)] = task;

            yield put(actionCreators.setItems(items));
            yield put(actionCreators.setCurrentItem(task));
            yield put(getTags.started(null));
        }),
];

{'fraction_non_alphanumeric': 0.138600374595607, 'fraction_numerical': 0.00034054146092286734, 'mean_word_length': 2.6896984924623117, 'pattern_counts': {'":': 0, '<': 13, '<?xml version=': 0, '>': 29, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4474194', 'n_tokens_mistral': 1718, 'n_tokens_neox': 1685, 'n_words': 373}