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          83x   83x         83x 83x 83x   83x 83x 83x 83x                 83x                                     83x                                                     83x                 83x                   83x               83x                                     83x  
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;