1111use App \Traits \AuthStatusTrait ;
1212use App \Traits \LoggingTrait ;
1313use App \Traits \TypeTrait ;
14- use Exception ;
1514use Illuminate \Contracts \View \View ;
15+ use Livewire \Attributes \Locked ;
1616use Livewire \Component ;
1717use Maize \Markable \Exceptions \InvalidMarkValueException ;
1818
@@ -26,25 +26,42 @@ final class FlagComponent extends Component
2626 private const string MODEL_PATH = 'app \\models \\' ;
2727
2828 public Comment |Post $ model ;
29+ public Flag |null $ userFlag = null ;
30+
31+ #[Locked]
32+ public int $ modelId ;
33+ #[Locked]
34+ public string $ type ;
35+ #[Locked]
2936 public int $ flagCount = 0 ;
37+ #[Locked]
3038 public string $ iconFilename = 'flag ' ;
31- public string $ note = '' ;
39+ #[Locked]
40+ public string $ titleText ;
41+ #[Locked]
3242 public array $ flagReasons = [];
43+
44+ // Actual values we interact with
45+ public string $ note = '' ;
3346 public string $ selectedReason = '' ;
34- public bool $ showForm = false ;
3547 public bool $ showNoteField = false ;
36- public string $ titleText ;
37- public string $ type ;
38- public bool $ userFlagged = false ;
48+ public bool $ formClosed = false ;
3949
4050 public function mount (
4151 Comment |Post $ model ,
4252 ): void {
4353 $ configReasons = config ('markable.allowed_values.flag ' , []);
44- $ this ->flagReasons = is_array ($ configReasons ) ? $ configReasons : [];
4554
55+ $ this ->flagReasons = is_array ($ configReasons ) ? array_combine (
56+ array_map (fn ($ reason ) => mb_strtolower (preg_replace ('/[^\w]+/ ' , '- ' , $ reason )), $ configReasons ),
57+ $ configReasons ,
58+ ) : [];
59+
60+ $ this ->formClosed = false ;
4661 $ this ->model = $ model ;
62+ $ this ->modelId = $ model ->id ;
4763 $ this ->type = $ this ->getType ();
64+ $ this ->userFlag = $ this ->getUserFlag ();
4865 $ this ->updateFlagData ();
4966 }
5067
@@ -53,77 +70,98 @@ public function render(): View
5370 return view ('livewire.flags.flag-component ' );
5471 }
5572
56- public function flagReasonSelected (string $ selectedReason ): void
73+ public function isNoteVisibleForReason (string $ reason ): bool
5774 {
58- if ($ selectedReason === self ::FLAG_WITH_NOTE ) {
59- $ this ->showNoteField = true ;
60- } else {
61- $ this ->showNoteField = false ;
62- $ this ->reset ('note ' );
63- }
75+ return $ reason === self ::FLAG_WITH_NOTE ;
76+ }
6477
65- $ this ->selectedReason = $ selectedReason ;
78+ public function getUserFlag (): Flag | null
79+ {
80+ return Flag::where ([
81+ 'user_id ' => auth ()->id (),
82+ 'markable_id ' => $ this ->model ->getKey (),
83+ 'markable_type ' => $ this ->model ->getMorphClass (),
84+ ])->first ();
6685 }
6786
68- public function updateFlagData (): void
87+ protected function updateFlagData (): void
6988 {
89+ $ value = $ this ->userFlag ?->value ?? '' ;
90+ $ this ->selectedReason = in_array ($ value , $ this ->flagReasons ) ? $ value : '' ;
91+ $ this ->note = $ this ->userFlag ?->metadata['note ' ] ?? '' ;
92+ $ this ->showNoteField = $ this ->isNoteVisibleForReason ($ this ->selectedReason );
7093 $ this ->setTitleText ();
7194 }
7295
73- public function store (): void
96+ protected function deleteUserFlag (): void
7497 {
75- // $rules = (new StoreFlagRequest())->rules();
98+ Flag::where ([
99+ 'user_id ' => auth ()->id (),
100+ 'markable_id ' => $ this ->model ->getKey (),
101+ 'markable_type ' => $ this ->model ->getMorphClass (),
102+ ])->get ()->each ->delete ();
103+ }
76104
77- // $this->validate($rules);
105+ public function store (): void
106+ {
78107 $ metadata = [];
79108
80109 $ selectedReason = mb_trim ($ this ->selectedReason );
110+ $ noteText = mb_trim ($ this ->note );
81111
82- try {
83- if ($ selectedReason === self ::FLAG_WITH_NOTE && mb_strlen ($ this ->note ) > 0 ) {
84- $ metadata = ['note ' => $ this ->note ];
85- }
86-
87- $ event = $ this ->type === 'comment ' ?
88- LivewireEventEnum::CommentFlagged->value :
89- LivewireEventEnum::PostFlagged->value ;
90-
91- $ this ->dispatchEvent ($ event );
112+ if ($ this ->isNoteVisibleForReason ($ selectedReason ) && mb_strlen ($ noteText ) > 0 ) {
113+ $ metadata = ['note ' => $ noteText ];
114+ }
92115
93- Flag::add ($ this ->model , auth ()->user (), $ selectedReason , $ metadata );
116+ // Just cancel the change if the form is unmodified
117+ if ($ selectedReason === ($ this ->userFlag ?->value ?? '' ) && $ metadata === $ this ->userFlag ?->metadata) {
118+ $ this ->cancel ();
119+ return ;
120+ }
94121
95- $ this ->showForm = false ;
122+ $ event = $ this ->type === 'comment ' ?
123+ LivewireEventEnum::CommentFlagged :
124+ LivewireEventEnum::PostFlagged;
96125
97- $ this ->userFlagged = false ;
126+ // Stop rendering while we are modifying data
127+ $ this ->formClosed = true ;
98128
99- $ this ->updateFlagData ();
129+ $ this ->deleteUserFlag ();
130+ try {
131+ $ this ->userFlag = Flag::add ($ this ->model , auth ()->user (), $ selectedReason , $ metadata );
100132 } catch (InvalidMarkValueException $ exception ) {
101133 $ this ->logError ($ exception );
102134 }
135+ $ this ->updateFlagData ();
136+
137+ $ this ->dispatchEvent ($ event );
103138 }
104139
105140 public function delete (): void
106141 {
107- try {
108- $ event = $ this ->type === 'comment ' ?
109- LivewireEventEnum::CommentFlagDeleted->value :
110- LivewireEventEnum::PostFlagDeleted->value ;
111-
112- $ this ->dispatchEvent ($ event );
113142
114- Flag::remove ($ this ->model , auth ()->user ());
143+ // Stop rendering while we are modifying data
144+ $ this ->formClosed = true ;
145+ $ event = $ this ->type === 'comment ' ?
146+ LivewireEventEnum::CommentFlagDeleted :
147+ LivewireEventEnum::PostFlagDeleted;
115148
116- $ this ->userFlagged = false ;
149+ $ this ->deleteUserFlag ();
150+ $ this ->userFlag = null ;
151+ $ this ->updateFlagData ();
117152
118- $ this ->updateFlagData ();
119- } catch (Exception $ exception ) {
120- $ this ->logError ($ exception );
121- }
153+ $ this ->dispatchEvent ($ event );
122154 }
123155
124- public function toggleForm (): void
156+ public function cancel (): void
125157 {
126- $ this ->showForm = !$ this ->showForm ;
158+ $ this ->formClosed = true ;
159+
160+ $ event = $ this ->type === 'comment ' ?
161+ LivewireEventEnum::CommentFlagCancelled :
162+ LivewireEventEnum::PostFlagCancelled;
163+
164+ $ this ->dispatchEvent ($ event );
127165 }
128166
129167 private function getType (): string
@@ -137,11 +175,11 @@ private function setTitleText(): void
137175 {
138176 $ flagText = 'Flag this ' . $ this ->type ;
139177
140- $ this ->titleText = $ this ->userFlagged ? trans ('Remove flag ' ) : trans ($ flagText );
178+ $ this ->titleText = $ this ->userFlag ? trans ('Remove or edit flag ' ) : trans ($ flagText );
141179 }
142180
143- private function dispatchEvent (string $ event ): void
181+ private function dispatchEvent (LivewireEventEnum $ event ): void
144182 {
145- $ this ->dispatch ($ event , id: $ this ->model ->id );
183+ $ this ->dispatch ($ event-> value , id: $ this ->model ->id );
146184 }
147185}
0 commit comments