1- import { FC , ReactNode , createContext , useState , useCallback } from "react" ;
2- import { useMultistepForm } from "../hooks/useMultistepForm" ;
3- import PageOne from "../components/form/PageOne" ;
4- import PageTwo from "../components/form/PageTwo" ;
5- import PageThree from "../components/form/PageThree" ;
6- import { Badge , BadgeDataTransfer , Card } from "../types" ;
7- import PageFour from "../components/form/PageFour" ;
1+ import { FC , ReactNode , createContext , useCallback , useState } from "react" ;
82import PageFive from "../components/form/PageFive" ;
3+ import PageFour from "../components/form/PageFour" ;
4+ import PageOne from "../components/form/PageOne" ;
95import PageSix from "../components/form/PageSix" ;
6+ import PageThree from "../components/form/PageThree" ;
7+ import PageTwo from "../components/form/PageTwo" ;
108import { INITIAL_CARD } from "../const" ;
9+ import { useMultistepForm } from "../hooks/useMultistepForm" ;
10+ import { Badge , BadgeDataTransfer , Card , Line } from "../types" ;
1111
1212export interface MultistepContextType {
1313 isFirstPage : boolean ;
@@ -22,9 +22,7 @@ export interface MultistepContextType {
2222 addBadge : ( lineNumber : number , badge : Omit < Badge , "position" > ) => void ;
2323 removeBadge : ( lineNumber : number , position : number ) => void ;
2424 grabbedBadge : BadgeDataTransfer | undefined ;
25- setGrabbedBadge : React . Dispatch <
26- React . SetStateAction < BadgeDataTransfer | undefined >
27- > ;
25+ setGrabbedBadge : ( grabbedBadge : BadgeDataTransfer | undefined ) => void ;
2826 insertBadge : (
2927 lineNumber : number ,
3028 position : number ,
@@ -63,82 +61,111 @@ export const MultistepProvider: FC<MultistepProviderProps> = ({ children }) => {
6361 < PageSix /> ,
6462 ] ) ;
6563
64+ /**
65+ * Updates the card in a way that none of the card's parameters is required.
66+ *
67+ * @param {Partial<Card> } updated
68+ */
6669 const updateCard = useCallback (
6770 ( updated : Partial < Card > ) => setCard ( ( prev ) => ( { ...prev , ...updated } ) ) ,
6871 [ ]
6972 ) ;
7073
71- const addBadge = useCallback (
72- ( lineNumber : number , badge : Omit < Badge , "position" > ) => {
74+ /**
75+ * Updates a line with the specified lineNumber.
76+ * If the line with the lineNumber is not presented, it does nothing.
77+ *
78+ * @param {number } lineNumber
79+ * @param {(line: Line) => void } callback
80+ */
81+ const updateLine = useCallback (
82+ ( lineNumber : number , callback : ( line : Line ) => void ) => {
7383 setCard ( ( prev ) => {
7484 // check whether the line exists
75- const line = prev . lines . findIndex ( ( x ) => x . lineNumber === lineNumber ) ;
76- if ( line === - 1 ) return prev ;
85+ const idx = prev . lines . findIndex ( ( x ) => x . lineNumber === lineNumber ) ;
86+ if ( idx === - 1 ) return prev ;
7787
7888 const newCard = structuredClone ( prev ) ;
79-
80- // update the badges
81- newCard . lines [ line ] . badges = [
82- ...newCard . lines [ line ] . badges ,
83- { ...badge , position : newCard . lines [ line ] . badges . length } ,
84- ] ;
89+ callback ( newCard . lines [ idx ] ) ;
8590
8691 return newCard ;
8792 } ) ;
8893 } ,
8994 [ ]
9095 ) ;
9196
92- const removeBadge = useCallback ( ( lineNumber : number , position : number ) => {
93- setCard ( ( prev ) => {
94- // check whether the line exists
95- const line = prev . lines . findIndex ( ( x ) => x . lineNumber === lineNumber ) ;
96- if ( line === - 1 ) return prev ;
97+ /**
98+ * Pushes a badge to the end of a line.
99+ * You should pass the badge without the position property.
100+ *
101+ * @param {number } lineNumber
102+ * @param {Omit<Badge, "position"> } badge
103+ */
104+ const addBadge = useCallback (
105+ ( lineNumber : number , badge : Omit < Badge , "position" > ) => {
106+ updateLine ( lineNumber , ( line ) => {
107+ const { badges } = line ;
108+ badges . push ( { position : badges . length , ...badge } ) ;
109+ } ) ;
110+ } ,
111+ [ updateLine ]
112+ ) ;
97113
98- const newCard = structuredClone ( prev ) ;
114+ /**
115+ * Removes a badge in the specified line at the specified position.
116+ *
117+ * @param {number } lineNumber
118+ * @param {number } position
119+ */
120+ const removeBadge = useCallback (
121+ ( lineNumber : number , position : number ) => {
122+ updateLine ( lineNumber , ( line ) => {
123+ const { badges } = line ;
99124
100- // remove the badge and rearrange the positions
101- newCard . lines [ line ] . badges = newCard . lines [ line ] . badges
102- . sort ( ( a , z ) => a . position - z . position )
103- . filter ( ( x ) => x . position !== position )
104- . map ( ( prev , i ) => ( { ...prev , position : i } ) ) ;
125+ // remove the old badge
126+ const idx = badges . map ( ( x ) => x . position ) . indexOf ( position ) ;
127+ if ( idx !== - 1 ) badges . splice ( idx , 1 ) ;
105128
106- return newCard ;
107- } ) ;
108- } , [ ] ) ;
129+ // rearrange the positions
130+ badges . forEach ( ( badge , i ) => ( badge . position = i ) ) ;
131+ } ) ;
132+ } ,
133+ [ updateLine ]
134+ ) ;
109135
136+ /**
137+ * Inserts a new badge in the specified line at a specified position.
138+ * This function also removes the old badge from the array.
139+ *
140+ * @param {number } lineNumber
141+ * @param {number } position
142+ * @param {BadgeDataTransfer } bdt
143+ */
110144 const insertBadge = useCallback (
111145 ( lineNumber : number , position : number , bdt : BadgeDataTransfer ) => {
112146 // If the grabbed badge is in the left side of the new position,
113147 // we need to decrement the position by one,
114148 // because we grabbed (technically removed) one from the new position's left side.
115149 if ( position > bdt . badge . position ) position -- ;
116150
117- setCard ( ( prev ) => {
118- // check whether the line exists
119- const line = prev . lines . findIndex ( ( x ) => x . lineNumber === lineNumber ) ;
120- if ( line === - 1 ) return prev ;
121-
122- const newCard = structuredClone ( prev ) ;
123- const badges = newCard . lines [ line ] . badges ;
124- const badgePositions = badges . map ( ( badge ) => badge . position ) ;
151+ updateLine ( lineNumber , ( line ) => {
152+ const { badges } = line ;
125153
126154 // remove the old badge
127- const idx = badgePositions . indexOf ( bdt . badge . position ) ;
155+ const idx = badges . map ( ( x ) => x . position ) . indexOf ( bdt . badge . position ) ;
128156 if ( idx !== - 1 ) badges . splice ( idx , 1 ) ;
129157
130158 // insert the new badge
131159 badges . splice ( position , 0 , bdt . badge ) ;
132-
133- // rearrange the positions
134160 badges . forEach ( ( badge , i ) => ( badge . position = i ) ) ;
135-
136- return newCard ;
137161 } ) ;
138162 } ,
139- [ ]
163+ [ updateLine ]
140164 ) ;
141165
166+ /**
167+ * Resets the card by setting it to it's initial state.
168+ */
142169 const resetCard = useCallback ( ( ) => {
143170 goToPageFirst ( ) ;
144171 setCard ( structuredClone ( INITIAL_CARD ) ) ;
0 commit comments