Index: ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/config/filter/InviteFilter.java
===================================================================
--- ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/config/filter/InviteFilter.java	(revision 2af3b2350cc1e659ea281d7fcc1a285eaf659392)
+++ ReserveNGo-backend/src/main/java/mk/ukim/finki/it/reservengo/config/filter/InviteFilter.java	(revision e5e2c49bae34ce01d852fe393742abff7490e2d0)
@@ -28,5 +28,14 @@
         String path = request.getRequestURI();
 
+
         if (path.contains("/register/local-manager") || path.contains("/register/local-worker") || path.contains("/register/invite/check")) {
+
+            //Solution for bug
+            if (request.getMethod().equals("OPTIONS")) {
+                filterChain.doFilter(request, response);
+                return;
+            }
+            //Solution for bug
+
             if (token == null || token.isEmpty()) {
                 response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
Index: ReserveNGo-frontend/src/Api_Classes/HttpClient.js
===================================================================
--- ReserveNGo-frontend/src/Api_Classes/HttpClient.js	(revision 2af3b2350cc1e659ea281d7fcc1a285eaf659392)
+++ ReserveNGo-frontend/src/Api_Classes/HttpClient.js	(revision e5e2c49bae34ce01d852fe393742abff7490e2d0)
@@ -100,9 +100,10 @@
     return this.json(endpoint, 'PUT', data, options)
   }
-
+  patch(endpoint, data, options = {}) {
+    return this.json(endpoint, 'PATCH', data, options)
+  }
   delete(endpoint, body= null, options = {}) {
     return this.json(endpoint, 'DELETE', body, options)
   }
-
   upload(endpoint, formData, options = {}) {
     return this.form(endpoint, 'POST', formData, options)
Index: ReserveNGo-frontend/src/components/Project/Customer/Profile_Page.vue
===================================================================
--- ReserveNGo-frontend/src/components/Project/Customer/Profile_Page.vue	(revision 2af3b2350cc1e659ea281d7fcc1a285eaf659392)
+++ ReserveNGo-frontend/src/components/Project/Customer/Profile_Page.vue	(revision e5e2c49bae34ce01d852fe393742abff7490e2d0)
@@ -2,164 +2,151 @@
 import { userStore } from '@/PiniaStores/UserStore.js'
 import blankProfile from '@/components/ectd/blank-profile.webp'
+import { useToasts } from '@/composables/useToast.js'
+import { isValidEmail } from '@/mixins/utilFunctions.js'
+import LoadingIcon from '@/components/Project/Utility/LoadingIcon.vue'
+import {useUser} from '@/repository/user.ts'
 
 export default {
+  components: { LoadingIcon },
   data() {
     return {
       userStore_: userStore(),
-      newFirstName: '',
-      newLastName: '',
-      newPhoneNumber: '',
-      newEmail: '',
       newPassword: '',
       currentPassword: '',
-
       profileData: {},
-
       isProfileImageButtonDisabled: true,
       profileImageSrc: null,
-
-      blankProfile: blankProfile
+      blankProfile: blankProfile,
+      showToast: useToasts().showToast,
+
+      isSavingDetails: false,
+      isUpdatingEmail: false,
+      isUpdatingPassword: false,
+      isUpdatingPicture: false,
     }
   },
   methods: {
     async updateProfileSettings() {
-      try {
-        const response = await fetch('http://localhost:8080/api/user/edit', {
-          method: 'PUT',
-          headers: {
-            'Content-Type': 'application/json',
-            Authorization: this.userStore_.getToken,
-          },
-          body: JSON.stringify({
-            firstName: this.profileData.firstName,
-            lastName: this.profileData.lastName,
-            phoneNumber: this.profileData.phoneNumber,
-          }),
+      this.isSavingDetails = true
+      try {
+        const payload = {
+          firstName: this.profileData.firstName,
+          lastName: this.profileData.lastName,
+          phoneNumber: this.profileData.phoneNumber,
+        }
+        const updatedUser = await useUser.updateProfile(payload)
+        this.userStore_.setNewEditedDataToLocalStorage(updatedUser)
+        this.showToast('Profile details saved successfully!', 'success')
+      } catch (err) {
+        this.showToast(err.response || 'Failed to save details.', 'error')
+      } finally {
+        this.isSavingDetails = false
+      }
+    },
+    async updateEmail() {
+      if (!isValidEmail(this.profileData.email)) {
+        this.showToast('Please enter a valid email address.', 'error')
+        return
+      }
+      this.isUpdatingEmail = true
+      try {
+        const payload = { newEmail: this.profileData.email }
+        const updatedTokenData = (await useUser.changeEmail(payload))
+        this.userStore_.setNewEmailToLocalStorage(updatedTokenData) // Assumes this updates the token with new email info
+        this.showToast(
+          'Email updated successfully! Please check your old email for confirmation.',
+          'success',
+        )
+      } catch (err) {
+        this.showToast(err.response || 'Failed to update email.', 'error')
+      } finally {
+        this.isUpdatingEmail = false
+      }
+    },
+    async updatePassword() {
+      this.isUpdatingPassword = true
+      try {
+        const payload = {
+          currentPassword: this.currentPassword,
+          newPassword: this.newPassword,
+        }
+        await useUser.changePassword(payload)
+        this.showToast('Password changed successfully.', 'success')
+        this.currentPassword = ''
+        this.newPassword = ''
+      } catch (err) {
+        this.showToast(err.response || 'Failed to change password.', 'error')
+      } finally {
+        this.isUpdatingPassword = false
+      }
+    },
+    async updateProfilePicture() {
+      const profilePictureFile = document.getElementById('profilePhotoInput').files[0]
+      if (!profilePictureFile) return
+
+      this.isUpdatingPicture = true
+      const formData = new FormData()
+      formData.append('avatar', profilePictureFile)
+
+      try {
+        const profileAvatarStringPath = await useUser.uploadAvatar(formData)
+
+        const response = await fetch('http://localhost:8080' + profileAvatarStringPath, {
+          headers: { Authorization: this.userStore_.getToken },
         })
-        const json = await response.json()
-        this.userStore_.setNewEditedDataToLocalStorage(json)
-      } catch (err) {
-        console.log(err)
-      }
-    },
-    async updateEmail() {
-      try {
-        const response = await fetch('http://localhost:8080/api/user/change-email', {
-          method: 'PATCH',
-          headers: {
-            'Content-Type': 'application/json',
-            Authorization: this.userStore_.getToken,
-          },
-          body: JSON.stringify({ newEmail: this.profileData.email }),
-        })
-        const json = await response.json()
-        this.userStore_.setNewEmailToLocalStorage(json)
-      } catch (err) {
-        console.log(err)
-      }
-    },
-    async updatePassword() {
-      try {
-        await fetch('http://localhost:8080/api/user/change-password', {
-          method: 'PATCH',
-          headers: {
-            'Content-Type': 'application/json',
-            Authorization: this.userStore_.getToken,
-          },
-          body: JSON.stringify({
-            currentPassword: this.currentPassword,
-            newPassword: this.newPassword,
-          }),
-        })
-      } catch (err) {
-        console.log(err)
-      }
-    },
-    updateProfilePicture() {
-      const profilePictureFile = document.getElementById('profilePhotoInput').files[0];
-      if (!profilePictureFile) return;
-
-      const formData = new FormData();
-      formData.append('avatar', profilePictureFile);
-
-      fetch('http://localhost:8080/api/user/upload-avatar', {
-        method: 'POST',
-        headers: {
-          Authorization: this.userStore_.getToken,
-        },
-        body: formData
-      })
-        .then(response => response.text())
-        .then(profileAvatarStringPath => {console.log("Profile Picture data returned", profileAvatarStringPath);
-
-
-
-            fetch('http://localhost:8080' + profileAvatarStringPath, {
-              headers: {
-                Authorization: this.userStore_.getToken,
-              }
-            })
-              .then(response => response.blob())
-              .then(blob => {
-                const reader = new FileReader();
-                reader.onloadend = () => {
-                  const base64data = reader.result;
-
-                  this.userStore_.setProfilePicturePathToLocalStorage(profileAvatarStringPath, base64data)
-                };
-                reader.readAsDataURL(blob);
-              })
-              .catch(err => console.log("Error parsing the blob", err))
-
-        })
-        .catch(err => console.log("Profile picture upload failed:", err));
-    },
-    deleteProfilePicture() {
-      fetch('http://localhost:8080/api/user/delete-avatar', {
-        method: 'DELETE',
-        headers: {
-          Authorization: this.userStore_.getToken,
+        const blob = await response.blob()
+        const reader = new FileReader()
+        reader.onloadend = () => {
+          this.userStore_.setProfilePicturePathToLocalStorage(
+            profileAvatarStringPath,
+            reader.result,
+          )
+          this.showToast('Profile picture updated!', 'success')
         }
-      })
-        .then(() => this.userStore_.removeProfilePictureFromLocaleStorage())
-        .catch(err => console.log("Erorr didnt remove profile picture", err))
+        reader.readAsDataURL(blob)
+      } catch (err) {
+        this.showToast(err.response || 'Profile picture upload failed.', 'error')
+      } finally {
+        this.isUpdatingPicture = false
+        this.isProfileImageButtonDisabled = true
+      }
+    },
+    async deleteProfilePicture() {
+      this.isUpdatingPicture = true
+      try {
+        await useUser.deleteAvatar()
+        this.userStore_.removeProfilePictureFromLocaleStorage()
+        this.showToast('Profile picture removed.', 'success')
+      } catch (err) {
+        this.showToast(err.response || 'Failed to remove profile picture.', 'error')
+      } finally {
+        this.isUpdatingPicture = false
+      }
+    },
+  },
+  async beforeMount() {
+    try {
+      this.profileData = await useUser.getProfile()
+    } catch (error) {
+      console.log('Error fetching profile settings', error)
+      this.showToast('Could not load your profile data.', 'error')
     }
-
-
-  },
-  beforeMount() {
-    fetch('http://localhost:8080/api/user/profile', {
-      method: 'GET',
-      headers: {
-        Authorization: this.userStore_.getToken,
-      },
-    })
-      .then((response) => response.json())
-      .then((data) => {
-        this.profileData = data
-        console.log('Priting response from profile api', this.profileData)
-      })
-      .catch((error) => {
-        console.log('Error fetching profile settings', error)
-      })
   },
   mounted() {
-    this.isProfileImageButtonDisabled = true;
-    const profilePictureImage = document.getElementById('profilePictureModal');
-    const inputProfilePicture = document.getElementById('profilePhotoInput');
+    this.isProfileImageButtonDisabled = true
+    const profilePictureImage = document.getElementById('profilePictureModal')
+    const inputProfilePicture = document.getElementById('profilePhotoInput')
 
     inputProfilePicture.addEventListener('change', (event) => {
-      this.isProfileImageButtonDisabled = false;
-
-      const file = event.target.files[0];
+      this.isProfileImageButtonDisabled = false
+      const file = event.target.files[0]
       if (file && file.type.startsWith('image/')) {
-        const reader = new FileReader();
+        const reader = new FileReader()
         reader.onload = (e) => {
-          profilePictureImage.src = e.target.result;
-        };
-        reader.readAsDataURL(file);
-      }
-    });
-
+          profilePictureImage.src = e.target.result
+        }
+        reader.readAsDataURL(file)
+      }
+    })
   },
 }
@@ -175,5 +162,5 @@
               <img
                 class="rounded-circle border me-3"
-                :src=" this.userStore_.data.profilePictureBase64Encoded || blankProfile"
+                :src="this.userStore_.data.profilePictureBase64Encoded || blankProfile"
                 alt="Profile Picture"
                 width="100"
@@ -182,9 +169,7 @@
             </div>
           </div>
-
           <h4>{{ profileData.firstName }} {{ profileData.lastName }}</h4>
           <p><strong>Email:</strong> {{ profileData.email }}</p>
           <p><strong>Phone Number:</strong> {{ profileData.phoneNumber }}</p>
-
           <button
             type="button"
@@ -218,6 +203,6 @@
             ></button>
           </div>
-
           <div class="modal-body">
+            <!-- Profile Picture Section -->
             <div class="d-flex justify-content-center">
               <div class="position-relative">
@@ -225,5 +210,5 @@
                   id="profilePictureModal"
                   class="rounded-circle border"
-                  :src=" this.userStore_.data.profilePictureBase64Encoded || blankProfile"
+                  :src="this.userStore_.data.profilePictureBase64Encoded || blankProfile"
                   alt="Profile Picture"
                   width="100"
@@ -236,5 +221,4 @@
                   accept="image/*"
                 />
-
                 <label
                   for="profilePhotoInput"
@@ -245,12 +229,28 @@
                 </label>
               </div>
-
             </div>
             <div class="d-flex justify-content-center">
-            <button v-if="userStore_.data.logoUrl == null" @click="updateProfilePicture" :class="{'disabled': this.isProfileImageButtonDisabled}" class="text-center btn btn-dark mb-3 mt-2">Save Picture</button>
-              <button v-if="userStore_.data.logoUrl != null" @click="deleteProfilePicture" class="text-center btn btn-dark mb-3 mt-2">Remove Picture</button>
-            </div>
-
-            <!-- Edit Name and Phone -->
+              <!-- --- MODIFIED: Added loading states to picture buttons --- -->
+              <button
+                v-if="!userStore_.data.profilePictureBase64Encoded"
+                @click="updateProfilePicture"
+                :disabled="isProfileImageButtonDisabled || isUpdatingPicture"
+                class="text-center btn btn-dark mb-3 mt-2"
+              >
+                <LoadingIcon v-if="isUpdatingPicture" />
+                Save Picture
+              </button>
+              <button
+                v-if="userStore_.data.profilePictureBase64Encoded"
+                @click="deleteProfilePicture"
+                :disabled="isUpdatingPicture"
+                class="text-center btn btn-dark mb-3 mt-2"
+              >
+                <LoadingIcon v-if="isUpdatingPicture" />
+                Remove Picture
+              </button>
+            </div>
+
+            <!-- Personal Details Section -->
             <h6>Personal Details</h6>
             <div class="mb-3">
@@ -262,7 +262,7 @@
                 class="form-control"
                 :placeholder="profileData.firstName"
-              />
-            </div>
-
+                :disabled="isSavingDetails"
+              />
+            </div>
             <div class="mb-3">
               <label for="lastName" class="form-label">Last Name</label>
@@ -273,7 +273,7 @@
                 class="form-control"
                 :placeholder="profileData.lastName"
-              />
-            </div>
-
+                :disabled="isSavingDetails"
+              />
+            </div>
             <div class="mb-3">
               <label for="phoneNumber" class="form-label">Phone Number</label>
@@ -284,31 +284,39 @@
                 class="form-control"
                 :placeholder="profileData.phoneNumber"
-              />
-            </div>
-
+                :disabled="isSavingDetails"
+              />
+            </div>
             <button
               @click="updateProfileSettings()"
               type="button"
               class="btn btn-dark w-100 mb-4"
-              data-bs-dismiss="modal"
+              :disabled="isSavingDetails"
             >
-              Save Changes
+              <LoadingIcon v-if="isSavingDetails" />
+              {{ isSavingDetails ? 'Saving...' : 'Save Changes' }}
             </button>
 
-            <!-- Change Email -->
+            <!-- Change Email Section -->
             <h6>Change Email</h6>
             <div class="input-group mb-3">
-              <input v-model="profileData.email" type="text" class="form-control" placeholder="New Email" />
+              <input
+                v-model="profileData.email"
+                type="text"
+                class="form-control"
+                placeholder="New Email"
+                :disabled="isUpdatingEmail"
+              />
               <button
                 @click="updateEmail()"
                 type="button"
                 class="btn btn-secondary"
-                data-bs-dismiss="modal"
+                :disabled="isUpdatingEmail"
               >
-                Update Email
+                <LoadingIcon v-if="isUpdatingEmail" />
+                {{ isUpdatingEmail ? 'Updating...' : 'Update Email' }}
               </button>
             </div>
 
-            <!-- Change Password -->
+            <!-- Change Password Section -->
             <h6>Change Password</h6>
             <div class="mb-2">
@@ -319,19 +327,25 @@
                 id="currentPassword"
                 class="form-control"
-              />
-            </div>
-
+                :disabled="isUpdatingPassword"
+              />
+            </div>
             <div class="mb-3">
               <label for="newPassword" class="form-label">New Password</label>
-              <input v-model="newPassword" type="password" id="newPassword" class="form-control" />
-            </div>
-
+              <input
+                v-model="newPassword"
+                type="password"
+                id="newPassword"
+                class="form-control"
+                :disabled="isUpdatingPassword"
+              />
+            </div>
             <button
               @click="updatePassword()"
               type="button"
               class="btn btn-secondary w-100"
-              data-bs-dismiss="modal"
+              :disabled="isUpdatingPassword"
             >
-              Change Password
+              <LoadingIcon v-if="isUpdatingPassword" />
+              {{ isUpdatingPassword ? 'Changing...' : 'Change Password' }}
             </button>
           </div>
Index: ReserveNGo-frontend/src/components/Project/Manager/ManagerDashboard.vue
===================================================================
--- ReserveNGo-frontend/src/components/Project/Manager/ManagerDashboard.vue	(revision 2af3b2350cc1e659ea281d7fcc1a285eaf659392)
+++ ReserveNGo-frontend/src/components/Project/Manager/ManagerDashboard.vue	(revision e5e2c49bae34ce01d852fe393742abff7490e2d0)
@@ -1,6 +1,11 @@
 <script>
 import { userStore } from '@/PiniaStores/UserStore.js'
+import LoadingIcon from '@/components/Project/Utility/LoadingIcon.vue'
+import { isValidEmail } from '@/mixins/utilFunctions.js'
+import { useLocalManager } from '@/repository/LocalManager.ts'
+import { useToasts } from '@/composables/useToast.js'
 
 export default {
+  components: { LoadingIcon },
   data() {
     return {
@@ -13,121 +18,119 @@
       sortKey: '',
       sortOrder: 'asc',
+      showToast: useToasts().showToast,
+      emailToWorker: '',
+      isEmailSending: false,
+
+      assigningWorkerId: null,
+      removingWorkerId: null,
     }
   },
   computed: {
     sortedWorkers() {
-      if (!this.sortKey) return this.workersForLocal;
-
+      if (!this.sortKey) return this.workersForLocal
       return [...this.workersForLocal].sort((a, b) => {
-        let valueA = a[this.sortKey] || '';
-        let valueB = b[this.sortKey] || '';
-
+        let valueA = a[this.sortKey] || ''
+        let valueB = b[this.sortKey] || ''
         if (typeof valueA === 'string') {
-          valueA = valueA.toLowerCase();
-          valueB = valueB.toLowerCase();
+          valueA = valueA.toLowerCase()
+          valueB = valueB.toLowerCase()
         }
-
-        if (valueA < valueB) return this.sortOrder === 'asc' ? -1 : 1;
-        if (valueA > valueB) return this.sortOrder === 'asc' ? 1 : -1;
-        return 0;
-      });
-    }
+        if (valueA < valueB) return this.sortOrder === 'asc' ? -1 : 1
+        if (valueA > valueB) return this.sortOrder === 'asc' ? 1 : -1
+        return 0
+      })
+    },
   },
   methods: {
     sortBy(key) {
       if (this.sortKey === key) {
-        this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc';
+        this.sortOrder = this.sortOrder === 'asc' ? 'desc' : 'asc'
       } else {
-        this.sortKey = key;
-        this.sortOrder = 'asc';
-      }
-    },
-    fetchWorkersForLocal() {
-      fetch('http://localhost:8080/api/local-manager/local-workers', {
-        method: 'GET',
-        headers: {
-          'Content-Type': 'application/json',
-          Authorization: this.user.getToken,
-        },
-      })
-        .then((res) => res.json())
-        .then((data) => (this.workersForLocal = data))
-        .catch((err) => console.log(err))
-    },
-    fetchWorkers() {
-      fetch('http://localhost:8080/api/local-manager/workers', {
-        method: 'GET',
-        headers: {
-          'Content-Type': 'application/json',
-          Authorization: this.user.getToken,
-        },
-      })
-        .then((res) => res.json())
-        .then((data) => (this.workers = data))
-        .catch((err) => console.log(err))
-    },
-    fetchLocal() {
-      fetch('http://localhost:8080/api/local-manager/my-local', {
-        method: 'GET',
-        headers: {
-          'Content-Type': 'application/json',
-          Authorization: this.user.getToken,
-        },
-      })
-        .then((res) => res.json())
-        .then((data) => (this.localId = data.id))
-        .catch((err) => console.log(err))
-    },
-    assignWorker(workerId) {
-      fetch(`http://localhost:8080/api/local-manager/assign/${workerId}`, {
-        method: 'POST',
-        headers: {
-          'Content-Type': 'application/json',
-          Authorization: this.user.getToken,
-        },
-      })
-        .then((response) => {
-          if (!response.ok) throw new Error('Failed to Assign worker.')
-          this.workers = this.workers.filter((worker) => worker.workerId !== workerId)
-          this.fetchWorkers()
-          this.fetchWorkersForLocal()
-        })
-        .catch((err) => console.log(err))
-    },
-    removeWorker(workerId) {
-      fetch(`http://localhost:8080/api/local-manager/remove/${workerId}`, {
-        method: 'DELETE',
-        headers: {
-          'Content-Type': 'application/json',
-          Authorization: this.user.getToken,
-        },
-      })
-        .then((response) => {
-          if (!response.ok) throw new Error('Failed to remove worker')
-          this.fetchWorkersForLocal()
-          this.fetchWorkers()
-        })
-        .catch((err) => console.log(err))
-    },
-    changeWorkerPosition(workerId, position) {
-      fetch(`http://localhost:8080/api/local-manager/change-position/${workerId}`, {
-        method: 'PUT',
-        headers: {
-          'Content-Type': 'application/json',
-          Authorization: this.user.getToken,
-        },
-        body: JSON.stringify({
-          position: position,
-        }),
-      })
-        .then((response) => {
-          if (!response.ok) throw new Error('Failed to change position');
-          this.fetchWorkersForLocal();
-        })
-        .catch(err => console.error('Error changing position:', err));
+        this.sortKey = key
+        this.sortOrder = 'asc'
+      }
+    },
+
+    async fetchWorkersForLocal() {
+      try {
+        this.workersForLocal = await useLocalManager.getLocalWorkers()
+      } catch (error) {
+        console.error('Failed to fetch local workers:', error)
+        this.showToast('Could not load your workers.', 'error')
+      }
+    },
+    async fetchWorkers() {
+      try {
+        this.workers = await useLocalManager.getAvailableWorkers()
+      } catch (error) {
+        console.error('Failed to fetch available workers:', error)
+      }
+    },
+    async fetchLocal() {
+      try {
+        const local = await useLocalManager.getMyLocal()
+        this.localId = local.id
+      } catch (error) {
+        console.error('Failed to fetch your local:', error)
+      }
+    },
+    async assignWorker(worker) {
+      this.assigningWorkerId = worker.id;
+      try {
+        await useLocalManager.assignWorker(worker.id)
+        this.showToast(`Assigned ${worker.firstName} successfully.`, 'success')
+        await this.fetchWorkers()
+        await this.fetchWorkersForLocal()
+      } catch (error) {
+        this.showToast(error.response || 'Failed to assign worker.', 'error')
+      } finally {
+        this.assigningWorkerId = null
+      }
+    },
+    async removeWorker(worker) {
+      this.removingWorkerId = worker.id;
+      try {
+        await useLocalManager.removeWorker(worker.id)
+        this.showToast(`Removed ${worker.firstName} successfully.`, 'success')
+        await this.fetchWorkersForLocal()
+      } catch (error) {
+        this.showToast(error.response || 'Failed to remove worker.', 'error')
+      } finally {
+        this.removingWorkerId = null
+      }
+    },
+    async changeWorkerPosition(workerId, position) {
+      try {
+        await useLocalManager.changeWorkerPosition(workerId, position)
+        this.showToast(`Position updated successfully.`, 'success')
+      } catch (error) {
+        this.showToast(error.response?.data?.message || 'Failed to change position.', 'error')
+        await this.fetchWorkersForLocal()
+      }
     },
     openAddWorkerModal() {
       this.fetchWorkers()
       this.showAddWorkerModal = true
+    },
+    async sendEmailToWorker() {
+      if (this.emailToWorker === '') {
+        this.showToast('Fill out the email form', 'error')
+        return
+      }
+      if (!isValidEmail(this.emailToWorker)) {
+        this.showToast('Please enter a valid email format', 'error')
+        return
+      }
+
+      this.isEmailSending = true
+      try {
+        await useLocalManager.inviteWorker(this.emailToWorker)
+        this.showToast(`Invite sent to ${this.emailToWorker}`, 'success')
+        this.emailToWorker = ''
+      } catch (error) {
+        this.showToast(error.response?.data?.message || 'Failed to send email.', 'error')
+      } finally {
+        this.isEmailSending = false
+      }
     },
   },
@@ -164,5 +167,12 @@
               >
                 <span>{{ worker.firstName }} {{ worker.lastName }} - {{ worker.email }}</span>
-                <button class="btn btn-sm btn-success" @click="assignWorker(worker.id)">Add</button>
+                <button
+                  class="btn btn-sm btn-success"
+                  @click="assignWorker(worker)"
+                  :disabled="assigningWorkerId === worker.id"
+                >
+                  <LoadingIcon v-if="assigningWorkerId === worker.id" />
+                  <span v-else>Add</span>
+                </button>
               </li>
             </ul>
@@ -176,52 +186,69 @@
       <table class="table table-striped table-hover align-middle">
         <thead class="table-light">
-        <tr>
-          <th style="cursor: pointer;" @click="sortBy('firstName')">
-            First Name
-            <span v-if="sortKey === 'firstName'">{{ sortOrder === 'asc' ? '↑' : '↓' }}</span>
-          </th>
-          <th style="cursor: pointer;" @click="sortBy('lastName')">
-            Last Name
-            <span v-if="sortKey === 'lastName'">{{ sortOrder === 'asc' ? '↑' : '↓' }}</span>
-          </th>
-          <th>Email</th>
-          <th>Phone Number</th>
-          <th style="cursor: pointer;" @click="sortBy('position')">
-            Position
-            <span v-if="sortKey === 'position'">{{ sortOrder === 'asc' ? '↑' : '↓' }}</span>
-          </th>
-          <th class="text-end">Actions</th>
-        </tr>
+          <tr>
+            <th style="cursor: pointer" @click="sortBy('firstName')">
+              First Name
+              <span v-if="sortKey === 'firstName'">{{ sortOrder === 'asc' ? '↑' : '↓' }}</span>
+            </th>
+            <th style="cursor: pointer" @click="sortBy('lastName')">
+              Last Name
+              <span v-if="sortKey === 'lastName'">{{ sortOrder === 'asc' ? '↑' : '↓' }}</span>
+            </th>
+            <th>Email</th>
+            <th>Phone Number</th>
+            <th style="cursor: pointer" @click="sortBy('position')">
+              Position
+              <span v-if="sortKey === 'position'">{{ sortOrder === 'asc' ? '↑' : '↓' }}</span>
+            </th>
+            <th class="text-end">Actions</th>
+          </tr>
         </thead>
         <tbody>
-        <tr v-for="worker in sortedWorkers" :key="worker.id">
-          <td>{{ worker.firstName }}</td>
-          <td>{{ worker.lastName }}</td>
-          <td>{{ worker.email }}</td>
-          <td>{{ worker.phoneNumber }}</td>
-          <td>
-            <select
-              class="form-select form-select-sm"
-              :value="worker.position"
-              @change="changeWorkerPosition(worker.id, $event.target.value)"
-            >
-              <option :value="null" selected disabled>
-                {{ worker.position ? worker.position : 'Assign Position' }}
-              </option>
-              <option v-for="pos in positions" :key="pos" :value="pos">
-                {{ pos }}
-              </option>
-            </select>
-          </td>
-          <td class="text-end">
-            <button class="btn btn-sm btn-outline-danger" @click="removeWorker(worker.id)">Remove</button>
-          </td>
-        </tr>
+          <tr v-for="worker in sortedWorkers" :key="worker.id">
+            <td>{{ worker.firstName }}</td>
+            <td>{{ worker.lastName }}</td>
+            <td>{{ worker.email }}</td>
+            <td>{{ worker.phoneNumber }}</td>
+            <td>
+              <select
+                class="form-select form-select-sm"
+                :value="worker.position"
+                @change="changeWorkerPosition(worker.id, $event.target.value)"
+              >
+                <option :value="null" selected disabled>
+                  {{ worker.position ? worker.position : 'Assign Position' }}
+                </option>
+                <option v-for="pos in positions" :key="pos" :value="pos">{{ pos }}</option>
+              </select>
+            </td>
+            <td class="text-end">
+              <button
+                class="btn btn-sm btn-outline-danger"
+                @click="removeWorker(worker)"
+                :disabled="removingWorkerId === worker.id"
+              >
+                <LoadingIcon v-if="removingWorkerId === worker.id" />
+                <span v-else>Remove</span>
+              </button>
+            </td>
+          </tr>
         </tbody>
       </table>
     </div>
 
-    <!-- Add Worker Button -->
     <button class="btn btn-success mt-3" @click="openAddWorkerModal">+ Add Worker</button>
+    <div id="sendMailGroup" class="mt-3">
+      <button @click="sendEmailToWorker" class="btn btn-success">
+        <LoadingIcon v-if="isEmailSending" />
+        <span v-else>+ </span>
+        Send worker register mail
+      </button>
+      <input
+        v-model="emailToWorker"
+        class="form-control"
+        type="text"
+        placeholder="Enter worker's email"
+      />
+    </div>
   </div>
 </template>
@@ -235,5 +262,4 @@
   overflow: hidden;
 }
-
 .container {
   max-width: 1200px;
@@ -245,10 +271,8 @@
   overflow: hidden;
 }
-
 .table-container {
   flex: 1 1 auto;
   overflow-y: auto;
 }
-
 table {
   font-size: 0.95rem;
@@ -256,5 +280,4 @@
   width: 100%;
 }
-
 th,
 td {
@@ -263,5 +286,4 @@
   text-overflow: ellipsis;
 }
-
 thead th {
   position: sticky;
@@ -271,12 +293,23 @@
   user-select: none;
 }
-
 th span {
   margin-left: 5px;
   font-size: 0.8rem;
 }
-
 .modal {
   display: block;
 }
+#sendMailGroup {
+  display: flex;
+}
+#sendMailGroup > .btn {
+  flex-shrink: 0;
+  border-bottom-right-radius: 0;
+  border-top-right-radius: 0;
+}
+#sendMailGroup > .form-control {
+  flex-grow: 1;
+  border-bottom-left-radius: 0;
+  border-top-left-radius: 0;
+}
 </style>
Index: ReserveNGo-frontend/src/repository/LocalManager.ts
===================================================================
--- ReserveNGo-frontend/src/repository/LocalManager.ts	(revision 2af3b2350cc1e659ea281d7fcc1a285eaf659392)
+++ ReserveNGo-frontend/src/repository/LocalManager.ts	(revision e5e2c49bae34ce01d852fe393742abff7490e2d0)
@@ -1,11 +1,6 @@
-import { ApiClient } from '@/Api_Classes/ApiClient'
 import { config } from '@/constants/Api_config'
 import { HttpClient } from '@/Api_Classes/HttpClient'
 
 const BASE_API_URL = config.API_BASE_URL
-
-/*
-console.warn("THIS IS THE BASE URL",BASE_API_URL)
-*/
 
 class LocalManager {
@@ -14,4 +9,28 @@
   constructor(baseUrl: string) {
     this.httpClient = new HttpClient(baseUrl)
+  }
+
+  getMyLocal(): Promise<any> {
+    return this.httpClient.get('my-local');
+  }
+
+  getLocalWorkers(): Promise<any[]> {
+    return this.httpClient.get('local-workers');
+  }
+
+  getAvailableWorkers(): Promise<any[]> {
+    return this.httpClient.get('workers');
+  }
+
+  assignWorker(workerId: string): Promise<any> {
+    return this.httpClient.post(`assign/${workerId}`, {});
+  }
+
+  removeWorker(workerId: string): Promise<any> {
+    return this.httpClient.delete(`remove/${workerId}`);
+  }
+
+  changeWorkerPosition(workerId: string, position: string): Promise<any> {
+    return this.httpClient.put(`change-position/${workerId}`, { position });
   }
 
@@ -23,18 +42,12 @@
   }
   deletePhoto(photoUrls : Object): Promise<any> {
-    /*if (typeof photoUrls === 'string') {photoUrls = [photoUrls] }*/
     return this.httpClient.delete('delete-photos', photoUrls)
-  }
-  getLocal(): Promise<any> {
-    return this.httpClient.get('my-local');
   }
   saveDetailChanges(payload): Promise<any> {
     return this.httpClient.put('my-local/edit', payload);
   }
-
   addEvent(formData: FormData): Promise<any> {
     return this.httpClient.post('add-event', formData)
   }
-
   updateEvent(formData: FormData, eventId): Promise<any> {
     return this.httpClient.put(`events/edit/${eventId}`, formData)
@@ -43,6 +56,8 @@
     return this.httpClient.delete(`delete-event/${eventId}`)
   }
-
+  inviteWorker(newEmail: string) : Promise<any> {
+    return this.httpClient.post('invite-worker', { newEmail })
+  }
 }
 
-export const useLocalManager = new LocalManager(BASE_API_URL + '/api/local-manager/', )
+export const useLocalManager = new LocalManager(BASE_API_URL + '/api/local-manager/')
Index: ReserveNGo-frontend/src/repository/user.ts
===================================================================
--- ReserveNGo-frontend/src/repository/user.ts	(revision e5e2c49bae34ce01d852fe393742abff7490e2d0)
+++ ReserveNGo-frontend/src/repository/user.ts	(revision e5e2c49bae34ce01d852fe393742abff7490e2d0)
@@ -0,0 +1,41 @@
+// src/repository/user.ts (or wherever you keep the file)
+import { config } from '@/constants/Api_config'
+import { HttpClient } from '@/Api_Classes/HttpClient'
+
+const BASE_API_URL = config.API_BASE_URL
+
+class UserManager { // Renamed for clarity, but you can keep LocalManager
+  private readonly httpClient: HttpClient
+
+  constructor(baseUrl: string) {
+    this.httpClient = new HttpClient(baseUrl)
+  }
+
+  // --- NEW METHODS BASED ON YOUR COMPONENT'S FETCH CALLS ---
+
+  getProfile(): Promise<any> {
+    return this.httpClient.get('profile');
+  }
+
+  updateProfile(payload: { firstName: string; lastName: string; phoneNumber: string }): Promise<any> {
+    return this.httpClient.put('edit', payload);
+  }
+
+  changeEmail(payload: { newEmail: string }): Promise<any> {
+    return this.httpClient.patch('change-email', payload);
+  }
+
+  changePassword(payload: { currentPassword: string; newPassword: string }): Promise<any> {
+    return this.httpClient.patch('change-password', payload);
+  }
+
+  uploadAvatar(formData: FormData): Promise<any> {
+    return this.httpClient.upload('upload-avatar', formData);
+  }
+
+  deleteAvatar(): Promise<any> {
+    return this.httpClient.delete('delete-avatar');
+  }
+}
+
+export const useUser = new UserManager(BASE_API_URL + '/api/user/')
