All files / src/store/features/entities/reducers notesReducers.ts

50% Statements 16/32
0% Branches 0/6
0% Functions 0/6
50% Lines 16/32

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122          91x   91x         91x 91x 91x   91x 91x 91x 91x                 91x                                     91x                                                     91x                 91x                   91x               91x                                     91x  
import {
  PayloadAction,
  CaseReducer,
  SliceCaseReducers,
} from "@reduxjs/toolkit";
import { v4 as uuid } from "uuid";
import { EntitiesState } from "shared/lib/entities/entitiesTypes";
import {
  defaultLocalisedNoteName,
  applyReparentEntityToCollection,
} from "shared/lib/entities/entitiesHelpers";
import { Note } from "shared/lib/resources/types";
import { notesAdapter } from "store/features/entities/adapters";
import { localNoteSelectTotal } from "store/features/entities/helpers";
import { MIN_WORLD_ENTITY_X, MIN_WORLD_ENTITY_Y } from "consts";
 
const MIN_NOTE_WIDTH = 20;
const MIN_NOTE_HEIGHT = 3;
const DEFAULT_NOTE_WIDTH = 20;
const DEFAULT_NOTE_HEIGHT = 15;
 
const addNote: CaseReducer<
  EntitiesState,
  PayloadAction<{
    noteId: string;
    x: number;
    y: number;
  }>
> = (state, action) => {
  const notesTotal = localNoteSelectTotal(state);
 
  const newNote: Note = {
    name: defaultLocalisedNoteName(notesTotal),
    id: action.payload.noteId,
    x: Math.max(MIN_WORLD_ENTITY_X, action.payload.x),
    y: Math.max(MIN_WORLD_ENTITY_Y, action.payload.y),
    width: DEFAULT_NOTE_WIDTH,
    height: DEFAULT_NOTE_HEIGHT,
    content: "",
  };
 
  notesAdapter.addOne(state.notes, newNote);
};
 
const editNote: CaseReducer<
  EntitiesState,
  PayloadAction<{ noteId: string; changes: Partial<Note> }>
> = (state, action) => {
  const note = state.notes.entities[action.payload.noteId];
  const patch = { ...action.payload.changes };
 
  if (!note) {
    return;
  }
 
  if (patch.width !== undefined) {
    patch.width = Math.max(MIN_NOTE_WIDTH, patch.width);
  }
 
  if (patch.height !== undefined) {
    patch.height = Math.max(MIN_NOTE_HEIGHT, patch.height);
  }
 
  notesAdapter.updateOne(state.notes, {
    id: action.payload.noteId,
    changes: patch,
  });
};
 
const removeNote: CaseReducer<
  EntitiesState,
  PayloadAction<{
    noteId: string;
  }>
> = (state, action) => {
  notesAdapter.removeOne(state.notes, action.payload.noteId);
};
 
const removeNotes: CaseReducer<
  EntitiesState,
  PayloadAction<{
    noteIds: string[];
  }>
> = (state, action) => {
  notesAdapter.removeMany(state.notes, action.payload.noteIds);
};
 
const reparentNote: CaseReducer<
  EntitiesState,
  PayloadAction<{
    noteId: string;
    toPath: string;
  }>
> = (state, action) => {
  applyReparentEntityToCollection(
    state.notes.entities,
    action.payload.noteId,
    action.payload.toPath,
  );
};
 
const notesReducers = {
  addNote: {
    reducer: addNote,
    prepare: (payload: { x: number; y: number }) => {
      return {
        payload: {
          ...payload,
          noteId: uuid(),
        },
      };
    },
  },
 
  editNote,
  removeNote,
  removeNotes,
  reparentNote,
} satisfies SliceCaseReducers<EntitiesState>;
 
export default notesReducers;