+  
      {
-    const accountId = rootState.route?.params?.accountId;
-    if (!accountId) return false;
+  isRTL: ($state, _getters, rootState, rootGetters) => {
+    const accountId = Number(rootState.route?.params?.accountId);
+    const userLocale = rootGetters?.getUISettings?.locale;
+    const accountLocale =
+      accountId && findRecordById($state, accountId)?.locale;
 
-    const { locale } = findRecordById($state, Number(accountId));
-    return locale ? getLanguageDirection(locale) : false;
+    // Prefer user locale; fallback to account locale
+    const effectiveLocale = userLocale ?? accountLocale;
+
+    return effectiveLocale ? getLanguageDirection(effectiveLocale) : false;
   },
   isTrialAccount: $state => id => {
     const account = findRecordById($state, id);
diff --git a/app/javascript/dashboard/store/modules/agentCapacityPolicies.js b/app/javascript/dashboard/store/modules/agentCapacityPolicies.js
new file mode 100644
index 000000000..ea554448f
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/agentCapacityPolicies.js
@@ -0,0 +1,316 @@
+import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
+import types from '../mutation-types';
+import AgentCapacityPoliciesAPI from '../../api/agentCapacityPolicies';
+import { throwErrorMessage } from '../utils/api';
+import camelcaseKeys from 'camelcase-keys';
+import snakecaseKeys from 'snakecase-keys';
+
+export const state = {
+  records: [],
+  uiFlags: {
+    isFetching: false,
+    isFetchingItem: false,
+    isCreating: false,
+    isUpdating: false,
+    isDeleting: false,
+  },
+  usersUiFlags: {
+    isFetching: false,
+    isDeleting: false,
+  },
+};
+
+export const getters = {
+  getAgentCapacityPolicies(_state) {
+    return _state.records;
+  },
+  getUIFlags(_state) {
+    return _state.uiFlags;
+  },
+  getUsersUIFlags(_state) {
+    return _state.usersUiFlags;
+  },
+  getAgentCapacityPolicyById: _state => id => {
+    return _state.records.find(record => record.id === Number(id)) || {};
+  },
+};
+
+export const actions = {
+  get: async function get({ commit }) {
+    commit(types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetching: true });
+    try {
+      const response = await AgentCapacityPoliciesAPI.get();
+      commit(
+        types.SET_AGENT_CAPACITY_POLICIES,
+        camelcaseKeys(response.data, { deep: true })
+      );
+    } catch (error) {
+      throwErrorMessage(error);
+    } finally {
+      commit(types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetching: false });
+    }
+  },
+
+  show: async function show({ commit }, policyId) {
+    commit(types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetchingItem: true });
+    try {
+      const response = await AgentCapacityPoliciesAPI.show(policyId);
+      const policy = camelcaseKeys(response.data, { deep: true });
+      commit(types.SET_AGENT_CAPACITY_POLICY, policy);
+    } catch (error) {
+      throwErrorMessage(error);
+    } finally {
+      commit(types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, {
+        isFetchingItem: false,
+      });
+    }
+  },
+
+  create: async function create({ commit }, policyObj) {
+    commit(types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isCreating: true });
+    try {
+      const response = await AgentCapacityPoliciesAPI.create(
+        snakecaseKeys(policyObj)
+      );
+      commit(
+        types.ADD_AGENT_CAPACITY_POLICY,
+        camelcaseKeys(response.data, { deep: true })
+      );
+      return response.data;
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    } finally {
+      commit(types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isCreating: false });
+    }
+  },
+
+  update: async function update({ commit }, { id, ...policyParams }) {
+    commit(types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isUpdating: true });
+    try {
+      const response = await AgentCapacityPoliciesAPI.update(
+        id,
+        snakecaseKeys(policyParams)
+      );
+      commit(
+        types.EDIT_AGENT_CAPACITY_POLICY,
+        camelcaseKeys(response.data, { deep: true })
+      );
+      return response.data;
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    } finally {
+      commit(types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isUpdating: false });
+    }
+  },
+
+  delete: async function deletePolicy({ commit }, policyId) {
+    commit(types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isDeleting: true });
+    try {
+      await AgentCapacityPoliciesAPI.delete(policyId);
+      commit(types.DELETE_AGENT_CAPACITY_POLICY, policyId);
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    } finally {
+      commit(types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isDeleting: false });
+    }
+  },
+
+  getUsers: async function getUsers({ commit }, policyId) {
+    commit(types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG, {
+      isFetching: true,
+    });
+    try {
+      const response = await AgentCapacityPoliciesAPI.getUsers(policyId);
+      commit(types.SET_AGENT_CAPACITY_POLICIES_USERS, {
+        policyId,
+        users: camelcaseKeys(response.data),
+      });
+      return response.data;
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    } finally {
+      commit(types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG, {
+        isFetching: false,
+      });
+    }
+  },
+
+  addUser: async function addUser({ commit }, { policyId, userData }) {
+    try {
+      const response = await AgentCapacityPoliciesAPI.addUser(
+        policyId,
+        userData
+      );
+      commit(types.ADD_AGENT_CAPACITY_POLICIES_USERS, {
+        policyId,
+        user: camelcaseKeys(response.data),
+      });
+      return response.data;
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    }
+  },
+
+  removeUser: async function removeUser({ commit }, { policyId, userId }) {
+    commit(types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG, {
+      isDeleting: true,
+    });
+    try {
+      await AgentCapacityPoliciesAPI.removeUser(policyId, userId);
+      commit(types.DELETE_AGENT_CAPACITY_POLICIES_USERS, { policyId, userId });
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    } finally {
+      commit(types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG, {
+        isDeleting: false,
+      });
+    }
+  },
+
+  createInboxLimit: async function createInboxLimit(
+    { commit },
+    { policyId, limitData }
+  ) {
+    try {
+      const response = await AgentCapacityPoliciesAPI.createInboxLimit(
+        policyId,
+        limitData
+      );
+      commit(
+        types.SET_AGENT_CAPACITY_POLICIES_INBOXES,
+        camelcaseKeys(response.data)
+      );
+      return response.data;
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    }
+  },
+
+  updateInboxLimit: async function updateInboxLimit(
+    { commit },
+    { policyId, limitId, limitData }
+  ) {
+    try {
+      const response = await AgentCapacityPoliciesAPI.updateInboxLimit(
+        policyId,
+        limitId,
+        limitData
+      );
+      commit(
+        types.EDIT_AGENT_CAPACITY_POLICIES_INBOXES,
+        camelcaseKeys(response.data)
+      );
+      return response.data;
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    }
+  },
+
+  deleteInboxLimit: async function deleteInboxLimit(
+    { commit },
+    { policyId, limitId }
+  ) {
+    try {
+      await AgentCapacityPoliciesAPI.deleteInboxLimit(policyId, limitId);
+      commit(types.DELETE_AGENT_CAPACITY_POLICIES_INBOXES, {
+        policyId,
+        limitId,
+      });
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    }
+  },
+};
+
+export const mutations = {
+  [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG](_state, data) {
+    _state.uiFlags = {
+      ..._state.uiFlags,
+      ...data,
+    };
+  },
+
+  [types.SET_AGENT_CAPACITY_POLICIES]: MutationHelpers.set,
+  [types.SET_AGENT_CAPACITY_POLICY]: MutationHelpers.setSingleRecord,
+  [types.ADD_AGENT_CAPACITY_POLICY]: MutationHelpers.create,
+  [types.EDIT_AGENT_CAPACITY_POLICY]: MutationHelpers.updateAttributes,
+  [types.DELETE_AGENT_CAPACITY_POLICY]: MutationHelpers.destroy,
+
+  [types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG](_state, data) {
+    _state.usersUiFlags = {
+      ..._state.usersUiFlags,
+      ...data,
+    };
+  },
+  [types.SET_AGENT_CAPACITY_POLICIES_USERS](_state, { policyId, users }) {
+    const policy = _state.records.find(p => p.id === policyId);
+    if (policy) {
+      policy.users = users;
+    }
+  },
+  [types.ADD_AGENT_CAPACITY_POLICIES_USERS](_state, { policyId, user }) {
+    const policy = _state.records.find(p => p.id === policyId);
+    if (policy) {
+      policy.users = policy.users || [];
+      policy.users.push(user);
+      policy.assignedAgentCount = policy.users.length;
+    }
+  },
+  [types.DELETE_AGENT_CAPACITY_POLICIES_USERS](_state, { policyId, userId }) {
+    const policy = _state.records.find(p => p.id === policyId);
+    if (policy) {
+      policy.users = (policy.users || []).filter(user => user.id !== userId);
+      policy.assignedAgentCount = policy.users.length;
+    }
+  },
+
+  [types.SET_AGENT_CAPACITY_POLICIES_INBOXES](_state, data) {
+    const policy = _state.records.find(
+      p => p.id === data.agentCapacityPolicyId
+    );
+    policy?.inboxCapacityLimits.push({
+      id: data.id,
+      inboxId: data.inboxId,
+      conversationLimit: data.conversationLimit,
+    });
+  },
+  [types.EDIT_AGENT_CAPACITY_POLICIES_INBOXES](_state, data) {
+    const policy = _state.records.find(
+      p => p.id === data.agentCapacityPolicyId
+    );
+    const limit = policy?.inboxCapacityLimits.find(l => l.id === data.id);
+    if (limit) {
+      Object.assign(limit, {
+        conversationLimit: data.conversationLimit,
+      });
+    }
+  },
+  [types.DELETE_AGENT_CAPACITY_POLICIES_INBOXES](
+    _state,
+    { policyId, limitId }
+  ) {
+    const policy = _state.records.find(p => p.id === policyId);
+    if (policy) {
+      policy.inboxCapacityLimits = policy.inboxCapacityLimits.filter(
+        limit => limit.id !== limitId
+      );
+    }
+  },
+};
+
+export default {
+  namespaced: true,
+  state,
+  getters,
+  actions,
+  mutations,
+};
diff --git a/app/javascript/dashboard/store/modules/assignmentPolicies.js b/app/javascript/dashboard/store/modules/assignmentPolicies.js
new file mode 100644
index 000000000..9ea2f49c3
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/assignmentPolicies.js
@@ -0,0 +1,232 @@
+import * as MutationHelpers from 'shared/helpers/vuex/mutationHelpers';
+import types from '../mutation-types';
+import AssignmentPoliciesAPI from '../../api/assignmentPolicies';
+import { throwErrorMessage } from '../utils/api';
+import camelcaseKeys from 'camelcase-keys';
+import snakecaseKeys from 'snakecase-keys';
+
+export const state = {
+  records: [],
+  uiFlags: {
+    isFetching: false,
+    isFetchingItem: false,
+    isCreating: false,
+    isUpdating: false,
+    isDeleting: false,
+  },
+  inboxUiFlags: {
+    isFetching: false,
+    isDeleting: false,
+  },
+};
+
+export const getters = {
+  getAssignmentPolicies(_state) {
+    return _state.records;
+  },
+  getUIFlags(_state) {
+    return _state.uiFlags;
+  },
+  getInboxUiFlags(_state) {
+    return _state.inboxUiFlags;
+  },
+  getAssignmentPolicyById: _state => id => {
+    return _state.records.find(record => record.id === Number(id)) || {};
+  },
+};
+
+export const actions = {
+  get: async function get({ commit }) {
+    commit(types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetching: true });
+    try {
+      const response = await AssignmentPoliciesAPI.get();
+      commit(types.SET_ASSIGNMENT_POLICIES, camelcaseKeys(response.data));
+    } catch (error) {
+      throwErrorMessage(error);
+    } finally {
+      commit(types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetching: false });
+    }
+  },
+
+  show: async function show({ commit }, policyId) {
+    commit(types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetchingItem: true });
+    try {
+      const response = await AssignmentPoliciesAPI.show(policyId);
+      const policy = camelcaseKeys(response.data);
+      commit(types.SET_ASSIGNMENT_POLICY, policy);
+    } catch (error) {
+      throwErrorMessage(error);
+    } finally {
+      commit(types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetchingItem: false });
+    }
+  },
+
+  create: async function create({ commit }, policyObj) {
+    commit(types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isCreating: true });
+    try {
+      const response = await AssignmentPoliciesAPI.create(
+        snakecaseKeys(policyObj)
+      );
+      commit(types.ADD_ASSIGNMENT_POLICY, camelcaseKeys(response.data));
+      return response.data;
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    } finally {
+      commit(types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isCreating: false });
+    }
+  },
+
+  update: async function update({ commit }, { id, ...policyParams }) {
+    commit(types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isUpdating: true });
+    try {
+      const response = await AssignmentPoliciesAPI.update(
+        id,
+        snakecaseKeys(policyParams)
+      );
+      commit(types.EDIT_ASSIGNMENT_POLICY, camelcaseKeys(response.data));
+      return response.data;
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    } finally {
+      commit(types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isUpdating: false });
+    }
+  },
+
+  delete: async function deletePolicy({ commit }, policyId) {
+    commit(types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isDeleting: true });
+    try {
+      await AssignmentPoliciesAPI.delete(policyId);
+      commit(types.DELETE_ASSIGNMENT_POLICY, policyId);
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    } finally {
+      commit(types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isDeleting: false });
+    }
+  },
+
+  getInboxes: async function getInboxes({ commit }, policyId) {
+    commit(types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isFetching: true });
+    try {
+      const response = await AssignmentPoliciesAPI.getInboxes(policyId);
+      commit(types.SET_ASSIGNMENT_POLICIES_INBOXES, {
+        policyId,
+        inboxes: camelcaseKeys(response.data.inboxes),
+      });
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    } finally {
+      commit(types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, {
+        isFetching: false,
+      });
+    }
+  },
+
+  setInboxPolicy: async function setInboxPolicy(
+    { commit },
+    { inboxId, policyId }
+  ) {
+    try {
+      const response = await AssignmentPoliciesAPI.setInboxPolicy(
+        inboxId,
+        policyId
+      );
+      commit(
+        types.ADD_ASSIGNMENT_POLICIES_INBOXES,
+        camelcaseKeys(response.data)
+      );
+      return response.data;
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    }
+  },
+
+  getInboxPolicy: async function getInboxPolicy(_, { inboxId }) {
+    try {
+      const response = await AssignmentPoliciesAPI.getInboxPolicy(inboxId);
+      return camelcaseKeys(response.data);
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    }
+  },
+
+  updateInboxPolicy: async function updateInboxPolicy({ commit }, { policy }) {
+    try {
+      commit(types.EDIT_ASSIGNMENT_POLICY, policy);
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    }
+  },
+
+  removeInboxPolicy: async function removeInboxPolicy(
+    { commit },
+    { policyId, inboxId }
+  ) {
+    commit(types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, {
+      isDeleting: true,
+    });
+    try {
+      await AssignmentPoliciesAPI.removeInboxPolicy(inboxId);
+      commit(types.DELETE_ASSIGNMENT_POLICIES_INBOXES, {
+        policyId,
+        inboxId,
+      });
+    } catch (error) {
+      throwErrorMessage(error);
+      throw error;
+    } finally {
+      commit(types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, {
+        isDeleting: false,
+      });
+    }
+  },
+};
+
+export const mutations = {
+  [types.SET_ASSIGNMENT_POLICIES_UI_FLAG](_state, data) {
+    _state.uiFlags = {
+      ..._state.uiFlags,
+      ...data,
+    };
+  },
+
+  [types.SET_ASSIGNMENT_POLICIES]: MutationHelpers.set,
+  [types.SET_ASSIGNMENT_POLICY]: MutationHelpers.setSingleRecord,
+  [types.ADD_ASSIGNMENT_POLICY]: MutationHelpers.create,
+  [types.EDIT_ASSIGNMENT_POLICY]: MutationHelpers.updateAttributes,
+  [types.DELETE_ASSIGNMENT_POLICY]: MutationHelpers.destroy,
+
+  [types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG](_state, data) {
+    _state.inboxUiFlags = {
+      ..._state.inboxUiFlags,
+      ...data,
+    };
+  },
+  [types.SET_ASSIGNMENT_POLICIES_INBOXES](_state, { policyId, inboxes }) {
+    const policy = _state.records.find(p => p.id === policyId);
+    if (policy) {
+      policy.inboxes = inboxes;
+    }
+  },
+  [types.DELETE_ASSIGNMENT_POLICIES_INBOXES](_state, { policyId, inboxId }) {
+    const policy = _state.records.find(p => p.id === policyId);
+    if (policy) {
+      policy.inboxes = policy?.inboxes?.filter(inbox => inbox.id !== inboxId);
+    }
+  },
+  [types.ADD_ASSIGNMENT_POLICIES_INBOXES]: MutationHelpers.updateAttributes,
+};
+
+export default {
+  namespaced: true,
+  state,
+  getters,
+  actions,
+  mutations,
+};
diff --git a/app/javascript/dashboard/store/modules/conversations/helpers/filterHelpers.js b/app/javascript/dashboard/store/modules/conversations/helpers/filterHelpers.js
index 3f1c32059..3d627e3ef 100644
--- a/app/javascript/dashboard/store/modules/conversations/helpers/filterHelpers.js
+++ b/app/javascript/dashboard/store/modules/conversations/helpers/filterHelpers.js
@@ -64,11 +64,13 @@ const getValueFromConversation = (conversation, attributeKey) => {
   switch (attributeKey) {
     case 'status':
     case 'priority':
-    case 'display_id':
     case 'labels':
     case 'created_at':
     case 'last_activity_at':
       return conversation[attributeKey];
+    case 'display_id':
+      // Frontend uses 'id' but backend expects 'display_id'
+      return conversation.display_id || conversation.id;
     case 'assignee_id':
       return conversation.meta?.assignee?.id;
     case 'inbox_id':
diff --git a/app/javascript/dashboard/store/modules/conversations/helpers/specs/filterHelpers.spec.js b/app/javascript/dashboard/store/modules/conversations/helpers/specs/filterHelpers.spec.js
index b36128819..096481c69 100644
--- a/app/javascript/dashboard/store/modules/conversations/helpers/specs/filterHelpers.spec.js
+++ b/app/javascript/dashboard/store/modules/conversations/helpers/specs/filterHelpers.spec.js
@@ -247,7 +247,7 @@ describe('filterHelpers', () => {
 
     // Text search tests - display_id
     it('should match conversation with equal_to operator for display_id', () => {
-      const conversation = { display_id: '12345' };
+      const conversation = { id: '12345' };
       const filters = [
         {
           attribute_key: 'display_id',
@@ -260,7 +260,7 @@ describe('filterHelpers', () => {
     });
 
     it('should match conversation with contains operator for display_id', () => {
-      const conversation = { display_id: '12345' };
+      const conversation = { id: '12345' };
       const filters = [
         {
           attribute_key: 'display_id',
@@ -273,7 +273,7 @@ describe('filterHelpers', () => {
     });
 
     it('should not match conversation with does_not_contain operator for display_id', () => {
-      const conversation = { display_id: '12345' };
+      const conversation = { id: '12345' };
       const filters = [
         {
           attribute_key: 'display_id',
@@ -286,7 +286,7 @@ describe('filterHelpers', () => {
     });
 
     it('should match conversation with does_not_contain operator when value is not present', () => {
-      const conversation = { display_id: '12345' };
+      const conversation = { id: '12345' };
       const filters = [
         {
           attribute_key: 'display_id',
@@ -989,7 +989,7 @@ describe('filterHelpers', () => {
 
     it('should handle empty string values in conversation', () => {
       const conversation = {
-        display_id: '',
+        id: '',
       };
       const filters = [
         {
diff --git a/app/javascript/dashboard/store/modules/inboxes.js b/app/javascript/dashboard/store/modules/inboxes.js
index c4789a7a9..9886be679 100644
--- a/app/javascript/dashboard/store/modules/inboxes.js
+++ b/app/javascript/dashboard/store/modules/inboxes.js
@@ -29,6 +29,9 @@ export const getters = {
   getInboxes($state) {
     return $state.records;
   },
+  getAllInboxes($state) {
+    return camelcaseKeys($state.records, { deep: true });
+  },
   getWhatsAppTemplates: $state => inboxId => {
     const [inbox] = $state.records.filter(
       record => record.id === Number(inboxId)
diff --git a/app/javascript/dashboard/store/modules/notifications/getters.js b/app/javascript/dashboard/store/modules/notifications/getters.js
index 4f4cafc9a..8af1d0360 100644
--- a/app/javascript/dashboard/store/modules/notifications/getters.js
+++ b/app/javascript/dashboard/store/modules/notifications/getters.js
@@ -38,4 +38,7 @@ export const getters = {
   getHasUnreadNotifications: $state => {
     return $state.meta.unreadCount > 0;
   },
+  getUnreadCount: $state => {
+    return $state.meta.unreadCount;
+  },
 };
diff --git a/app/javascript/dashboard/store/modules/specs/account/getters.spec.js b/app/javascript/dashboard/store/modules/specs/account/getters.spec.js
index 77cc9b357..f354faca2 100644
--- a/app/javascript/dashboard/store/modules/specs/account/getters.spec.js
+++ b/app/javascript/dashboard/store/modules/specs/account/getters.spec.js
@@ -49,35 +49,74 @@ describe('#getters', () => {
   });
 
   describe('isRTL', () => {
-    it('returns false when accountId is not present', () => {
+    afterEach(() => {
+      vi.restoreAllMocks();
+    });
+
+    it('returns false when accountId is not present and userLocale is not set', () => {
+      const state = { records: [accountData] };
       const rootState = { route: { params: {} } };
-      expect(getters.isRTL({}, null, rootState)).toBe(false);
+      const rootGetters = {};
+
+      expect(getters.isRTL(state, null, rootState, rootGetters)).toBe(false);
     });
 
-    it('returns true for RTL language', () => {
-      const state = {
-        records: [{ id: 1, locale: 'ar' }],
-      };
-      const rootState = { route: { params: { accountId: '1' } } };
-      vi.spyOn(languageHelpers, 'getLanguageDirection').mockReturnValue(true);
-      expect(getters.isRTL(state, null, rootState)).toBe(true);
+    it('uses userLocale when present (no accountId)', () => {
+      const state = { records: [accountData] };
+      const rootState = { route: { params: {} } };
+      const rootGetters = { getUISettings: { locale: 'ar' } };
+      const spy = vi
+        .spyOn(languageHelpers, 'getLanguageDirection')
+        .mockReturnValue(true);
+
+      expect(getters.isRTL(state, null, rootState, rootGetters)).toBe(true);
+      expect(spy).toHaveBeenCalledWith('ar');
     });
 
-    it('returns false for LTR language', () => {
-      const state = {
-        records: [{ id: 1, locale: 'en' }],
-      };
+    it('prefers userLocale over account locale when both are present', () => {
+      const state = { records: [{ id: 1, locale: 'en' }] };
       const rootState = { route: { params: { accountId: '1' } } };
-      vi.spyOn(languageHelpers, 'getLanguageDirection').mockReturnValue(false);
-      expect(getters.isRTL(state, null, rootState)).toBe(false);
+      const rootGetters = { getUISettings: { locale: 'ar' } };
+      const spy = vi
+        .spyOn(languageHelpers, 'getLanguageDirection')
+        .mockReturnValue(true);
+
+      expect(getters.isRTL(state, null, rootState, rootGetters)).toBe(true);
+      expect(spy).toHaveBeenCalledWith('ar');
     });
 
-    it('returns false when account is not found', () => {
-      const state = {
-        records: [],
-      };
+    it('falls back to account locale when userLocale is not provided', () => {
+      const state = { records: [{ id: 1, locale: 'ar' }] };
       const rootState = { route: { params: { accountId: '1' } } };
-      expect(getters.isRTL(state, null, rootState)).toBe(false);
+      const rootGetters = {};
+      const spy = vi
+        .spyOn(languageHelpers, 'getLanguageDirection')
+        .mockReturnValue(true);
+
+      expect(getters.isRTL(state, null, rootState, rootGetters)).toBe(true);
+      expect(spy).toHaveBeenCalledWith('ar');
+    });
+
+    it('returns false for LTR language when userLocale is provided', () => {
+      const state = { records: [{ id: 1, locale: 'en' }] };
+      const rootState = { route: { params: { accountId: '1' } } };
+      const rootGetters = { getUISettings: { locale: 'en' } };
+      const spy = vi
+        .spyOn(languageHelpers, 'getLanguageDirection')
+        .mockReturnValue(false);
+
+      expect(getters.isRTL(state, null, rootState, rootGetters)).toBe(false);
+      expect(spy).toHaveBeenCalledWith('en');
+    });
+
+    it('returns false when accountId present but user locale is null', () => {
+      const state = { records: [{ id: 1, locale: 'en' }] };
+      const rootState = { route: { params: { accountId: '1' } } };
+      const rootGetters = { getUISettings: { locale: null } };
+      const spy = vi.spyOn(languageHelpers, 'getLanguageDirection');
+
+      expect(getters.isRTL(state, null, rootState, rootGetters)).toBe(false);
+      expect(spy).toHaveBeenCalledWith('en');
     });
   });
 });
diff --git a/app/javascript/dashboard/store/modules/specs/agentCapacityPolicies/actions.spec.js b/app/javascript/dashboard/store/modules/specs/agentCapacityPolicies/actions.spec.js
new file mode 100644
index 000000000..3414a2086
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/specs/agentCapacityPolicies/actions.spec.js
@@ -0,0 +1,408 @@
+import axios from 'axios';
+import { actions } from '../../agentCapacityPolicies';
+import types from '../../../mutation-types';
+import agentCapacityPoliciesList, {
+  camelCaseFixtures,
+  mockUsers,
+  mockInboxLimits,
+  camelCaseMockInboxLimits,
+} from './fixtures';
+import camelcaseKeys from 'camelcase-keys';
+import snakecaseKeys from 'snakecase-keys';
+
+const commit = vi.fn();
+
+global.axios = axios;
+vi.mock('axios');
+vi.mock('camelcase-keys');
+vi.mock('snakecase-keys');
+vi.mock('../../../utils/api');
+
+describe('#actions', () => {
+  beforeEach(() => {
+    vi.clearAllMocks();
+  });
+
+  describe('#get', () => {
+    it('sends correct actions if API is success', async () => {
+      axios.get.mockResolvedValue({ data: agentCapacityPoliciesList });
+      camelcaseKeys.mockReturnValue(camelCaseFixtures);
+
+      await actions.get({ commit });
+
+      expect(camelcaseKeys).toHaveBeenCalledWith(agentCapacityPoliciesList, {
+        deep: true,
+      });
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetching: true }],
+        [types.SET_AGENT_CAPACITY_POLICIES, camelCaseFixtures],
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetching: false }],
+      ]);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.get.mockRejectedValue({ message: 'Incorrect header' });
+
+      await actions.get({ commit });
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetching: true }],
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetching: false }],
+      ]);
+    });
+  });
+
+  describe('#show', () => {
+    it('sends correct actions if API is success', async () => {
+      const policyData = agentCapacityPoliciesList[0];
+      const camelCasedPolicy = camelCaseFixtures[0];
+
+      axios.get.mockResolvedValue({ data: policyData });
+      camelcaseKeys.mockReturnValue(camelCasedPolicy);
+
+      await actions.show({ commit }, 1);
+
+      expect(camelcaseKeys).toHaveBeenCalledWith(policyData, {
+        deep: true,
+      });
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetchingItem: true }],
+        [types.SET_AGENT_CAPACITY_POLICY, camelCasedPolicy],
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetchingItem: false }],
+      ]);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.get.mockRejectedValue({ message: 'Not found' });
+
+      await actions.show({ commit }, 1);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetchingItem: true }],
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isFetchingItem: false }],
+      ]);
+    });
+  });
+
+  describe('#create', () => {
+    it('sends correct actions if API is success', async () => {
+      const newPolicy = agentCapacityPoliciesList[0];
+      const camelCasedData = camelCaseFixtures[0];
+      const snakeCasedPolicy = { default_capacity: 10 };
+
+      axios.post.mockResolvedValue({ data: newPolicy });
+      camelcaseKeys.mockReturnValue(camelCasedData);
+      snakecaseKeys.mockReturnValue(snakeCasedPolicy);
+
+      const result = await actions.create({ commit }, newPolicy);
+
+      expect(snakecaseKeys).toHaveBeenCalledWith(newPolicy);
+      expect(camelcaseKeys).toHaveBeenCalledWith(newPolicy, {
+        deep: true,
+      });
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isCreating: true }],
+        [types.ADD_AGENT_CAPACITY_POLICY, camelCasedData],
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isCreating: false }],
+      ]);
+      expect(result).toEqual(newPolicy);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.post.mockRejectedValue(new Error('Validation error'));
+
+      await expect(actions.create({ commit }, {})).rejects.toThrow(Error);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isCreating: true }],
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isCreating: false }],
+      ]);
+    });
+  });
+
+  describe('#update', () => {
+    it('sends correct actions if API is success', async () => {
+      const updateParams = { id: 1, name: 'Updated Policy' };
+      const responseData = {
+        ...agentCapacityPoliciesList[0],
+        name: 'Updated Policy',
+      };
+      const camelCasedData = {
+        ...camelCaseFixtures[0],
+        name: 'Updated Policy',
+      };
+      const snakeCasedParams = { name: 'Updated Policy' };
+
+      axios.patch.mockResolvedValue({ data: responseData });
+      camelcaseKeys.mockReturnValue(camelCasedData);
+      snakecaseKeys.mockReturnValue(snakeCasedParams);
+
+      const result = await actions.update({ commit }, updateParams);
+
+      expect(snakecaseKeys).toHaveBeenCalledWith({ name: 'Updated Policy' });
+      expect(camelcaseKeys).toHaveBeenCalledWith(responseData, {
+        deep: true,
+      });
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isUpdating: true }],
+        [types.EDIT_AGENT_CAPACITY_POLICY, camelCasedData],
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isUpdating: false }],
+      ]);
+      expect(result).toEqual(responseData);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.patch.mockRejectedValue(new Error('Validation error'));
+
+      await expect(
+        actions.update({ commit }, { id: 1, name: 'Test' })
+      ).rejects.toThrow(Error);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isUpdating: true }],
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isUpdating: false }],
+      ]);
+    });
+  });
+
+  describe('#delete', () => {
+    it('sends correct actions if API is success', async () => {
+      const policyId = 1;
+      axios.delete.mockResolvedValue({});
+
+      await actions.delete({ commit }, policyId);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isDeleting: true }],
+        [types.DELETE_AGENT_CAPACITY_POLICY, policyId],
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isDeleting: false }],
+      ]);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.delete.mockRejectedValue(new Error('Not found'));
+
+      await expect(actions.delete({ commit }, 1)).rejects.toThrow(Error);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isDeleting: true }],
+        [types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG, { isDeleting: false }],
+      ]);
+    });
+  });
+
+  describe('#getUsers', () => {
+    it('sends correct actions if API is success', async () => {
+      const policyId = 1;
+      const userData = [
+        { id: 1, name: 'Agent 1', email: 'agent1@example.com', capacity: 15 },
+        { id: 2, name: 'Agent 2', email: 'agent2@example.com', capacity: 20 },
+      ];
+      const camelCasedUsers = [
+        { id: 1, name: 'Agent 1', email: 'agent1@example.com', capacity: 15 },
+        { id: 2, name: 'Agent 2', email: 'agent2@example.com', capacity: 20 },
+      ];
+
+      axios.get.mockResolvedValue({ data: userData });
+      camelcaseKeys.mockReturnValue(camelCasedUsers);
+
+      const result = await actions.getUsers({ commit }, policyId);
+
+      expect(camelcaseKeys).toHaveBeenCalledWith(userData);
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG, { isFetching: true }],
+        [
+          types.SET_AGENT_CAPACITY_POLICIES_USERS,
+          { policyId, users: camelCasedUsers },
+        ],
+        [
+          types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG,
+          { isFetching: false },
+        ],
+      ]);
+      expect(result).toEqual(userData);
+    });
+
+    it('sends correct actions if API fails', async () => {
+      axios.get.mockRejectedValue(new Error('API Error'));
+
+      await expect(actions.getUsers({ commit }, 1)).rejects.toThrow(Error);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG, { isFetching: true }],
+        [
+          types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG,
+          { isFetching: false },
+        ],
+      ]);
+    });
+  });
+
+  describe('#addUser', () => {
+    it('sends correct actions if API is success', async () => {
+      const policyId = 1;
+      const userData = { user_id: 3, capacity: 12 };
+      const responseData = mockUsers[2];
+      const camelCasedUser = mockUsers[2];
+
+      axios.post.mockResolvedValue({ data: responseData });
+      camelcaseKeys.mockReturnValue(camelCasedUser);
+
+      const result = await actions.addUser({ commit }, { policyId, userData });
+
+      expect(camelcaseKeys).toHaveBeenCalledWith(responseData);
+      expect(commit.mock.calls).toEqual([
+        [
+          types.ADD_AGENT_CAPACITY_POLICIES_USERS,
+          { policyId, user: camelCasedUser },
+        ],
+      ]);
+      expect(result).toEqual(responseData);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.post.mockRejectedValue(new Error('Validation error'));
+
+      await expect(
+        actions.addUser({ commit }, { policyId: 1, userData: {} })
+      ).rejects.toThrow(Error);
+
+      expect(commit).not.toHaveBeenCalled();
+    });
+  });
+
+  describe('#removeUser', () => {
+    it('sends correct actions if API is success', async () => {
+      const policyId = 1;
+      const userId = 2;
+      axios.delete.mockResolvedValue({});
+
+      await actions.removeUser({ commit }, { policyId, userId });
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG, { isDeleting: true }],
+        [types.DELETE_AGENT_CAPACITY_POLICIES_USERS, { policyId, userId }],
+        [
+          types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG,
+          { isDeleting: false },
+        ],
+      ]);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.delete.mockRejectedValue(new Error('Not found'));
+
+      await expect(
+        actions.removeUser({ commit }, { policyId: 1, userId: 2 })
+      ).rejects.toThrow(Error);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG, { isDeleting: true }],
+        [
+          types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG,
+          { isDeleting: false },
+        ],
+      ]);
+    });
+  });
+
+  describe('#createInboxLimit', () => {
+    it('sends correct actions if API is success', async () => {
+      const policyId = 1;
+      const limitData = { inbox_id: 3, conversation_limit: 20 };
+      const responseData = mockInboxLimits[2];
+      const camelCasedData = camelCaseMockInboxLimits[2];
+
+      axios.post.mockResolvedValue({ data: responseData });
+      camelcaseKeys.mockReturnValue(camelCasedData);
+
+      const result = await actions.createInboxLimit(
+        { commit },
+        { policyId, limitData }
+      );
+
+      expect(camelcaseKeys).toHaveBeenCalledWith(responseData);
+      expect(commit.mock.calls).toEqual([
+        [types.SET_AGENT_CAPACITY_POLICIES_INBOXES, camelCasedData],
+      ]);
+      expect(result).toEqual(responseData);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.post.mockRejectedValue(new Error('Validation error'));
+
+      await expect(
+        actions.createInboxLimit({ commit }, { policyId: 1, limitData: {} })
+      ).rejects.toThrow(Error);
+
+      expect(commit).not.toHaveBeenCalled();
+    });
+  });
+
+  describe('#updateInboxLimit', () => {
+    it('sends correct actions if API is success', async () => {
+      const policyId = 1;
+      const limitId = 1;
+      const limitData = { conversation_limit: 25 };
+      const responseData = {
+        ...mockInboxLimits[0],
+        conversation_limit: 25,
+      };
+      const camelCasedData = {
+        ...camelCaseMockInboxLimits[0],
+        conversationLimit: 25,
+      };
+
+      axios.put.mockResolvedValue({ data: responseData });
+      camelcaseKeys.mockReturnValue(camelCasedData);
+
+      const result = await actions.updateInboxLimit(
+        { commit },
+        { policyId, limitId, limitData }
+      );
+
+      expect(camelcaseKeys).toHaveBeenCalledWith(responseData);
+      expect(commit.mock.calls).toEqual([
+        [types.EDIT_AGENT_CAPACITY_POLICIES_INBOXES, camelCasedData],
+      ]);
+      expect(result).toEqual(responseData);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.put.mockRejectedValue(new Error('Validation error'));
+
+      await expect(
+        actions.updateInboxLimit(
+          { commit },
+          { policyId: 1, limitId: 1, limitData: {} }
+        )
+      ).rejects.toThrow(Error);
+
+      expect(commit).not.toHaveBeenCalled();
+    });
+  });
+
+  describe('#deleteInboxLimit', () => {
+    it('sends correct actions if API is success', async () => {
+      const policyId = 1;
+      const limitId = 1;
+      axios.delete.mockResolvedValue({});
+
+      await actions.deleteInboxLimit({ commit }, { policyId, limitId });
+
+      expect(commit.mock.calls).toEqual([
+        [types.DELETE_AGENT_CAPACITY_POLICIES_INBOXES, { policyId, limitId }],
+      ]);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.delete.mockRejectedValue(new Error('Not found'));
+
+      await expect(
+        actions.deleteInboxLimit({ commit }, { policyId: 1, limitId: 1 })
+      ).rejects.toThrow(Error);
+
+      expect(commit).not.toHaveBeenCalled();
+    });
+  });
+});
diff --git a/app/javascript/dashboard/store/modules/specs/agentCapacityPolicies/fixtures.js b/app/javascript/dashboard/store/modules/specs/agentCapacityPolicies/fixtures.js
new file mode 100644
index 000000000..c79597919
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/specs/agentCapacityPolicies/fixtures.js
@@ -0,0 +1,199 @@
+export default [
+  {
+    id: 1,
+    name: 'Standard Capacity Policy',
+    description: 'Default capacity policy for agents',
+    default_capacity: 10,
+    enabled: true,
+    account_id: 1,
+    assigned_agent_count: 3,
+    created_at: '2024-01-01T10:00:00.000Z',
+    updated_at: '2024-01-01T10:00:00.000Z',
+    users: [],
+    inbox_capacity_limits: [
+      {
+        id: 1,
+        inbox_id: 1,
+        conversation_limit: 15,
+        agent_capacity_policy_id: 1,
+      },
+      {
+        id: 2,
+        inbox_id: 2,
+        conversation_limit: 8,
+        agent_capacity_policy_id: 1,
+      },
+    ],
+  },
+  {
+    id: 2,
+    name: 'High Capacity Policy',
+    description: 'High capacity policy for senior agents',
+    default_capacity: 20,
+    enabled: true,
+    account_id: 1,
+    assigned_agent_count: 5,
+    created_at: '2024-01-01T11:00:00.000Z',
+    updated_at: '2024-01-01T11:00:00.000Z',
+    users: [
+      {
+        id: 1,
+        name: 'Agent Smith',
+        email: 'agent.smith@example.com',
+        capacity: 25,
+      },
+      {
+        id: 2,
+        name: 'Agent Johnson',
+        email: 'agent.johnson@example.com',
+        capacity: 18,
+      },
+    ],
+    inbox_capacity_limits: [],
+  },
+  {
+    id: 3,
+    name: 'Disabled Policy',
+    description: 'Disabled capacity policy',
+    default_capacity: 5,
+    enabled: false,
+    account_id: 1,
+    assigned_agent_count: 0,
+    created_at: '2024-01-01T12:00:00.000Z',
+    updated_at: '2024-01-01T12:00:00.000Z',
+    users: [],
+    inbox_capacity_limits: [],
+  },
+];
+
+export const camelCaseFixtures = [
+  {
+    id: 1,
+    name: 'Standard Capacity Policy',
+    description: 'Default capacity policy for agents',
+    defaultCapacity: 10,
+    enabled: true,
+    accountId: 1,
+    assignedAgentCount: 3,
+    createdAt: '2024-01-01T10:00:00.000Z',
+    updatedAt: '2024-01-01T10:00:00.000Z',
+    users: [],
+    inboxCapacityLimits: [
+      {
+        id: 1,
+        inboxId: 1,
+        conversationLimit: 15,
+        agentCapacityPolicyId: 1,
+      },
+      {
+        id: 2,
+        inboxId: 2,
+        conversationLimit: 8,
+        agentCapacityPolicyId: 1,
+      },
+    ],
+  },
+  {
+    id: 2,
+    name: 'High Capacity Policy',
+    description: 'High capacity policy for senior agents',
+    defaultCapacity: 20,
+    enabled: true,
+    accountId: 1,
+    assignedAgentCount: 5,
+    createdAt: '2024-01-01T11:00:00.000Z',
+    updatedAt: '2024-01-01T11:00:00.000Z',
+    users: [
+      {
+        id: 1,
+        name: 'Agent Smith',
+        email: 'agent.smith@example.com',
+        capacity: 25,
+      },
+      {
+        id: 2,
+        name: 'Agent Johnson',
+        email: 'agent.johnson@example.com',
+        capacity: 18,
+      },
+    ],
+    inboxCapacityLimits: [],
+  },
+  {
+    id: 3,
+    name: 'Disabled Policy',
+    description: 'Disabled capacity policy',
+    defaultCapacity: 5,
+    enabled: false,
+    accountId: 1,
+    assignedAgentCount: 0,
+    createdAt: '2024-01-01T12:00:00.000Z',
+    updatedAt: '2024-01-01T12:00:00.000Z',
+    users: [],
+    inboxCapacityLimits: [],
+  },
+];
+
+// Additional test data for user and inbox limit operations
+export const mockUsers = [
+  {
+    id: 1,
+    name: 'Agent Smith',
+    email: 'agent.smith@example.com',
+    capacity: 25,
+  },
+  {
+    id: 2,
+    name: 'Agent Johnson',
+    email: 'agent.johnson@example.com',
+    capacity: 18,
+  },
+  {
+    id: 3,
+    name: 'Agent Brown',
+    email: 'agent.brown@example.com',
+    capacity: 12,
+  },
+];
+
+export const mockInboxLimits = [
+  {
+    id: 1,
+    inbox_id: 1,
+    conversation_limit: 15,
+    agent_capacity_policy_id: 1,
+  },
+  {
+    id: 2,
+    inbox_id: 2,
+    conversation_limit: 8,
+    agent_capacity_policy_id: 1,
+  },
+  {
+    id: 3,
+    inbox_id: 3,
+    conversation_limit: 20,
+    agent_capacity_policy_id: 2,
+  },
+];
+
+export const camelCaseMockInboxLimits = [
+  {
+    id: 1,
+    inboxId: 1,
+    conversationLimit: 15,
+    agentCapacityPolicyId: 1,
+  },
+  {
+    id: 2,
+    inboxId: 2,
+    conversationLimit: 8,
+    agentCapacityPolicyId: 1,
+  },
+  {
+    id: 3,
+    inboxId: 3,
+    conversationLimit: 20,
+    agentCapacityPolicyId: 2,
+  },
+];
diff --git a/app/javascript/dashboard/store/modules/specs/agentCapacityPolicies/getters.spec.js b/app/javascript/dashboard/store/modules/specs/agentCapacityPolicies/getters.spec.js
new file mode 100644
index 000000000..2acd00ad4
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/specs/agentCapacityPolicies/getters.spec.js
@@ -0,0 +1,51 @@
+import { getters } from '../../agentCapacityPolicies';
+import agentCapacityPoliciesList from './fixtures';
+
+describe('#getters', () => {
+  it('getAgentCapacityPolicies', () => {
+    const state = { records: agentCapacityPoliciesList };
+    expect(getters.getAgentCapacityPolicies(state)).toEqual(
+      agentCapacityPoliciesList
+    );
+  });
+
+  it('getUIFlags', () => {
+    const state = {
+      uiFlags: {
+        isFetching: true,
+        isFetchingItem: false,
+        isCreating: false,
+        isUpdating: false,
+        isDeleting: false,
+      },
+    };
+    expect(getters.getUIFlags(state)).toEqual({
+      isFetching: true,
+      isFetchingItem: false,
+      isCreating: false,
+      isUpdating: false,
+      isDeleting: false,
+    });
+  });
+
+  it('getUsersUIFlags', () => {
+    const state = {
+      usersUiFlags: {
+        isFetching: false,
+        isDeleting: false,
+      },
+    };
+    expect(getters.getUsersUIFlags(state)).toEqual({
+      isFetching: false,
+      isDeleting: false,
+    });
+  });
+
+  it('getAgentCapacityPolicyById', () => {
+    const state = { records: agentCapacityPoliciesList };
+    expect(getters.getAgentCapacityPolicyById(state)(1)).toEqual(
+      agentCapacityPoliciesList[0]
+    );
+    expect(getters.getAgentCapacityPolicyById(state)(4)).toEqual({});
+  });
+});
diff --git a/app/javascript/dashboard/store/modules/specs/agentCapacityPolicies/mutations.spec.js b/app/javascript/dashboard/store/modules/specs/agentCapacityPolicies/mutations.spec.js
new file mode 100644
index 000000000..f6cfba80d
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/specs/agentCapacityPolicies/mutations.spec.js
@@ -0,0 +1,619 @@
+import { mutations } from '../../agentCapacityPolicies';
+import types from '../../../mutation-types';
+import agentCapacityPoliciesList, { mockUsers } from './fixtures';
+
+describe('#mutations', () => {
+  describe('#SET_AGENT_CAPACITY_POLICIES_UI_FLAG', () => {
+    it('sets single ui flag', () => {
+      const state = {
+        uiFlags: {
+          isFetching: false,
+          isCreating: false,
+        },
+      };
+
+      mutations[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG](state, {
+        isFetching: true,
+      });
+
+      expect(state.uiFlags).toEqual({
+        isFetching: true,
+        isCreating: false,
+      });
+    });
+
+    it('sets multiple ui flags', () => {
+      const state = {
+        uiFlags: {
+          isFetching: false,
+          isCreating: false,
+          isUpdating: false,
+        },
+      };
+
+      mutations[types.SET_AGENT_CAPACITY_POLICIES_UI_FLAG](state, {
+        isFetching: true,
+        isCreating: true,
+      });
+
+      expect(state.uiFlags).toEqual({
+        isFetching: true,
+        isCreating: true,
+        isUpdating: false,
+      });
+    });
+  });
+
+  describe('#SET_AGENT_CAPACITY_POLICIES', () => {
+    it('sets agent capacity policies records', () => {
+      const state = { records: [] };
+
+      mutations[types.SET_AGENT_CAPACITY_POLICIES](
+        state,
+        agentCapacityPoliciesList
+      );
+
+      expect(state.records).toEqual(agentCapacityPoliciesList);
+    });
+
+    it('replaces existing records', () => {
+      const state = { records: [{ id: 999, name: 'Old Policy' }] };
+
+      mutations[types.SET_AGENT_CAPACITY_POLICIES](
+        state,
+        agentCapacityPoliciesList
+      );
+
+      expect(state.records).toEqual(agentCapacityPoliciesList);
+    });
+  });
+
+  describe('#SET_AGENT_CAPACITY_POLICY', () => {
+    it('sets single agent capacity policy record', () => {
+      const state = { records: [] };
+
+      mutations[types.SET_AGENT_CAPACITY_POLICY](
+        state,
+        agentCapacityPoliciesList[0]
+      );
+
+      expect(state.records).toEqual([agentCapacityPoliciesList[0]]);
+    });
+
+    it('replaces existing record', () => {
+      const state = { records: [{ id: 1, name: 'Old Policy' }] };
+
+      mutations[types.SET_AGENT_CAPACITY_POLICY](
+        state,
+        agentCapacityPoliciesList[0]
+      );
+
+      expect(state.records).toEqual([agentCapacityPoliciesList[0]]);
+    });
+  });
+
+  describe('#ADD_AGENT_CAPACITY_POLICY', () => {
+    it('adds new policy to empty records', () => {
+      const state = { records: [] };
+
+      mutations[types.ADD_AGENT_CAPACITY_POLICY](
+        state,
+        agentCapacityPoliciesList[0]
+      );
+
+      expect(state.records).toEqual([agentCapacityPoliciesList[0]]);
+    });
+
+    it('adds new policy to existing records', () => {
+      const state = { records: [agentCapacityPoliciesList[0]] };
+
+      mutations[types.ADD_AGENT_CAPACITY_POLICY](
+        state,
+        agentCapacityPoliciesList[1]
+      );
+
+      expect(state.records).toEqual([
+        agentCapacityPoliciesList[0],
+        agentCapacityPoliciesList[1],
+      ]);
+    });
+  });
+
+  describe('#EDIT_AGENT_CAPACITY_POLICY', () => {
+    it('updates existing policy by id', () => {
+      const state = {
+        records: [
+          { ...agentCapacityPoliciesList[0] },
+          { ...agentCapacityPoliciesList[1] },
+        ],
+      };
+
+      const updatedPolicy = {
+        ...agentCapacityPoliciesList[0],
+        name: 'Updated Policy Name',
+        description: 'Updated Description',
+      };
+
+      mutations[types.EDIT_AGENT_CAPACITY_POLICY](state, updatedPolicy);
+
+      expect(state.records[0]).toEqual(updatedPolicy);
+      expect(state.records[1]).toEqual(agentCapacityPoliciesList[1]);
+    });
+
+    it('updates policy with camelCase properties', () => {
+      const camelCasePolicy = {
+        id: 1,
+        name: 'Camel Case Policy',
+        defaultCapacity: 15,
+        enabled: true,
+      };
+
+      const state = {
+        records: [camelCasePolicy],
+      };
+
+      const updatedPolicy = {
+        ...camelCasePolicy,
+        name: 'Updated Camel Case',
+        defaultCapacity: 25,
+      };
+
+      mutations[types.EDIT_AGENT_CAPACITY_POLICY](state, updatedPolicy);
+
+      expect(state.records[0]).toEqual(updatedPolicy);
+    });
+
+    it('does nothing if policy id not found', () => {
+      const state = {
+        records: [agentCapacityPoliciesList[0]],
+      };
+
+      const nonExistentPolicy = {
+        id: 999,
+        name: 'Non-existent',
+      };
+
+      const originalRecords = [...state.records];
+      mutations[types.EDIT_AGENT_CAPACITY_POLICY](state, nonExistentPolicy);
+
+      expect(state.records).toEqual(originalRecords);
+    });
+  });
+
+  describe('#DELETE_AGENT_CAPACITY_POLICY', () => {
+    it('deletes policy by id', () => {
+      const state = {
+        records: [agentCapacityPoliciesList[0], agentCapacityPoliciesList[1]],
+      };
+
+      mutations[types.DELETE_AGENT_CAPACITY_POLICY](state, 1);
+
+      expect(state.records).toEqual([agentCapacityPoliciesList[1]]);
+    });
+
+    it('does nothing if id not found', () => {
+      const state = {
+        records: [agentCapacityPoliciesList[0]],
+      };
+
+      mutations[types.DELETE_AGENT_CAPACITY_POLICY](state, 999);
+
+      expect(state.records).toEqual([agentCapacityPoliciesList[0]]);
+    });
+
+    it('handles empty records', () => {
+      const state = { records: [] };
+
+      mutations[types.DELETE_AGENT_CAPACITY_POLICY](state, 1);
+
+      expect(state.records).toEqual([]);
+    });
+  });
+
+  describe('#SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG', () => {
+    it('sets users ui flags', () => {
+      const state = {
+        usersUiFlags: {
+          isFetching: false,
+        },
+      };
+
+      mutations[types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG](state, {
+        isFetching: true,
+      });
+
+      expect(state.usersUiFlags).toEqual({
+        isFetching: true,
+      });
+    });
+
+    it('merges with existing flags', () => {
+      const state = {
+        usersUiFlags: {
+          isFetching: false,
+          isDeleting: true,
+        },
+      };
+
+      mutations[types.SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG](state, {
+        isFetching: true,
+      });
+
+      expect(state.usersUiFlags).toEqual({
+        isFetching: true,
+        isDeleting: true,
+      });
+    });
+  });
+
+  describe('#SET_AGENT_CAPACITY_POLICIES_USERS', () => {
+    it('sets users for existing policy', () => {
+      const testUsers = [
+        { id: 1, name: 'Agent 1', email: 'agent1@example.com', capacity: 15 },
+        { id: 2, name: 'Agent 2', email: 'agent2@example.com', capacity: 20 },
+      ];
+
+      const state = {
+        records: [
+          { id: 1, name: 'Policy 1', users: [] },
+          { id: 2, name: 'Policy 2', users: [] },
+        ],
+      };
+
+      mutations[types.SET_AGENT_CAPACITY_POLICIES_USERS](state, {
+        policyId: 1,
+        users: testUsers,
+      });
+
+      expect(state.records[0].users).toEqual(testUsers);
+      expect(state.records[1].users).toEqual([]);
+    });
+
+    it('replaces existing users', () => {
+      const oldUsers = [{ id: 99, name: 'Old Agent', capacity: 5 }];
+      const newUsers = [{ id: 1, name: 'New Agent', capacity: 15 }];
+
+      const state = {
+        records: [{ id: 1, name: 'Policy 1', users: oldUsers }],
+      };
+
+      mutations[types.SET_AGENT_CAPACITY_POLICIES_USERS](state, {
+        policyId: 1,
+        users: newUsers,
+      });
+
+      expect(state.records[0].users).toEqual(newUsers);
+    });
+
+    it('does nothing if policy not found', () => {
+      const state = {
+        records: [{ id: 1, name: 'Policy 1', users: [] }],
+      };
+
+      const originalState = JSON.parse(JSON.stringify(state));
+
+      mutations[types.SET_AGENT_CAPACITY_POLICIES_USERS](state, {
+        policyId: 999,
+        users: [{ id: 1, name: 'Test' }],
+      });
+
+      expect(state).toEqual(originalState);
+    });
+  });
+
+  describe('#ADD_AGENT_CAPACITY_POLICIES_USERS', () => {
+    it('adds user to existing policy', () => {
+      const state = {
+        records: [
+          { id: 1, name: 'Policy 1', users: [] },
+          { id: 2, name: 'Policy 2', users: [] },
+        ],
+      };
+
+      mutations[types.ADD_AGENT_CAPACITY_POLICIES_USERS](state, {
+        policyId: 1,
+        user: mockUsers[0],
+      });
+
+      expect(state.records[0].users).toEqual([mockUsers[0]]);
+      expect(state.records[1].users).toEqual([]);
+    });
+
+    it('adds user to policy with existing users', () => {
+      const state = {
+        records: [{ id: 1, name: 'Policy 1', users: [mockUsers[0]] }],
+      };
+
+      mutations[types.ADD_AGENT_CAPACITY_POLICIES_USERS](state, {
+        policyId: 1,
+        user: mockUsers[1],
+      });
+
+      expect(state.records[0].users).toEqual([mockUsers[0], mockUsers[1]]);
+    });
+
+    it('initializes users array if undefined', () => {
+      const state = {
+        records: [{ id: 1, name: 'Policy 1' }],
+      };
+
+      mutations[types.ADD_AGENT_CAPACITY_POLICIES_USERS](state, {
+        policyId: 1,
+        user: mockUsers[0],
+      });
+
+      expect(state.records[0].users).toEqual([mockUsers[0]]);
+    });
+
+    it('updates assigned agent count', () => {
+      const state = {
+        records: [{ id: 1, name: 'Policy 1', users: [] }],
+      };
+
+      mutations[types.ADD_AGENT_CAPACITY_POLICIES_USERS](state, {
+        policyId: 1,
+        user: mockUsers[0],
+      });
+
+      expect(state.records[0].assignedAgentCount).toEqual(1);
+    });
+  });
+
+  describe('#DELETE_AGENT_CAPACITY_POLICIES_USERS', () => {
+    it('removes user from policy', () => {
+      const state = {
+        records: [
+          {
+            id: 1,
+            name: 'Policy 1',
+            users: [mockUsers[0], mockUsers[1], mockUsers[2]],
+          },
+        ],
+      };
+
+      mutations[types.DELETE_AGENT_CAPACITY_POLICIES_USERS](state, {
+        policyId: 1,
+        userId: 2,
+      });
+
+      expect(state.records[0].users).toEqual([mockUsers[0], mockUsers[2]]);
+    });
+
+    it('handles removing non-existent user', () => {
+      const state = {
+        records: [
+          {
+            id: 1,
+            name: 'Policy 1',
+            users: [mockUsers[0]],
+          },
+        ],
+      };
+
+      mutations[types.DELETE_AGENT_CAPACITY_POLICIES_USERS](state, {
+        policyId: 1,
+        userId: 999,
+      });
+
+      expect(state.records[0].users).toEqual([mockUsers[0]]);
+    });
+
+    it('updates assigned agent count', () => {
+      const state = {
+        records: [{ id: 1, name: 'Policy 1', users: [mockUsers[0]] }],
+      };
+
+      mutations[types.DELETE_AGENT_CAPACITY_POLICIES_USERS](state, {
+        policyId: 1,
+        userId: 1,
+      });
+
+      expect(state.records[0].assignedAgentCount).toEqual(0);
+    });
+  });
+
+  describe('#SET_AGENT_CAPACITY_POLICIES_INBOXES', () => {
+    it('adds inbox limit to policy', () => {
+      const state = {
+        records: [
+          {
+            id: 1,
+            name: 'Policy 1',
+            inboxCapacityLimits: [],
+          },
+        ],
+      };
+
+      const inboxLimitData = {
+        id: 1,
+        inboxId: 1,
+        conversationLimit: 15,
+        agentCapacityPolicyId: 1,
+      };
+
+      mutations[types.SET_AGENT_CAPACITY_POLICIES_INBOXES](
+        state,
+        inboxLimitData
+      );
+
+      expect(state.records[0].inboxCapacityLimits).toEqual([
+        {
+          id: 1,
+          inboxId: 1,
+          conversationLimit: 15,
+        },
+      ]);
+    });
+
+    it('does nothing if policy not found', () => {
+      const state = {
+        records: [{ id: 1, name: 'Policy 1', inboxCapacityLimits: [] }],
+      };
+
+      const originalState = JSON.parse(JSON.stringify(state));
+
+      mutations[types.SET_AGENT_CAPACITY_POLICIES_INBOXES](state, {
+        id: 1,
+        inboxId: 1,
+        conversationLimit: 15,
+        agentCapacityPolicyId: 999,
+      });
+
+      expect(state).toEqual(originalState);
+    });
+  });
+
+  describe('#EDIT_AGENT_CAPACITY_POLICIES_INBOXES', () => {
+    it('updates existing inbox limit', () => {
+      const state = {
+        records: [
+          {
+            id: 1,
+            name: 'Policy 1',
+            inboxCapacityLimits: [
+              {
+                id: 1,
+                inboxId: 1,
+                conversationLimit: 15,
+              },
+              {
+                id: 2,
+                inboxId: 2,
+                conversationLimit: 8,
+              },
+            ],
+          },
+        ],
+      };
+
+      mutations[types.EDIT_AGENT_CAPACITY_POLICIES_INBOXES](state, {
+        id: 1,
+        inboxId: 1,
+        conversationLimit: 25,
+        agentCapacityPolicyId: 1,
+      });
+
+      expect(state.records[0].inboxCapacityLimits[0]).toEqual({
+        id: 1,
+        inboxId: 1,
+        conversationLimit: 25,
+      });
+      expect(state.records[0].inboxCapacityLimits[1]).toEqual({
+        id: 2,
+        inboxId: 2,
+        conversationLimit: 8,
+      });
+    });
+
+    it('does nothing if limit not found', () => {
+      const state = {
+        records: [
+          {
+            id: 1,
+            name: 'Policy 1',
+            inboxCapacityLimits: [
+              {
+                id: 1,
+                inboxId: 1,
+                conversationLimit: 15,
+              },
+            ],
+          },
+        ],
+      };
+
+      const originalLimits = [...state.records[0].inboxCapacityLimits];
+
+      mutations[types.EDIT_AGENT_CAPACITY_POLICIES_INBOXES](state, {
+        id: 999,
+        inboxId: 1,
+        conversationLimit: 25,
+        agentCapacityPolicyId: 1,
+      });
+
+      expect(state.records[0].inboxCapacityLimits).toEqual(originalLimits);
+    });
+
+    it('does nothing if policy not found', () => {
+      const state = {
+        records: [{ id: 1, name: 'Policy 1', inboxCapacityLimits: [] }],
+      };
+
+      const originalState = JSON.parse(JSON.stringify(state));
+
+      mutations[types.EDIT_AGENT_CAPACITY_POLICIES_INBOXES](state, {
+        id: 1,
+        inboxId: 1,
+        conversationLimit: 25,
+        agentCapacityPolicyId: 999,
+      });
+
+      expect(state).toEqual(originalState);
+    });
+  });
+
+  describe('#DELETE_AGENT_CAPACITY_POLICIES_INBOXES', () => {
+    it('removes inbox limit from policy', () => {
+      const state = {
+        records: [
+          {
+            id: 1,
+            name: 'Policy 1',
+            inboxCapacityLimits: [
+              {
+                id: 1,
+                inboxId: 1,
+                conversationLimit: 15,
+              },
+              {
+                id: 2,
+                inboxId: 2,
+                conversationLimit: 8,
+              },
+            ],
+          },
+        ],
+      };
+
+      mutations[types.DELETE_AGENT_CAPACITY_POLICIES_INBOXES](state, {
+        policyId: 1,
+        limitId: 1,
+      });
+
+      expect(state.records[0].inboxCapacityLimits).toEqual([
+        {
+          id: 2,
+          inboxId: 2,
+          conversationLimit: 8,
+        },
+      ]);
+    });
+
+    it('handles removing non-existent limit', () => {
+      const state = {
+        records: [
+          {
+            id: 1,
+            name: 'Policy 1',
+            inboxCapacityLimits: [
+              {
+                id: 1,
+                inboxId: 1,
+                conversationLimit: 15,
+              },
+            ],
+          },
+        ],
+      };
+
+      const originalLimits = [...state.records[0].inboxCapacityLimits];
+
+      mutations[types.DELETE_AGENT_CAPACITY_POLICIES_INBOXES](state, {
+        policyId: 1,
+        limitId: 999,
+      });
+
+      expect(state.records[0].inboxCapacityLimits).toEqual(originalLimits);
+    });
+  });
+});
diff --git a/app/javascript/dashboard/store/modules/specs/assignmentPolicies/actions.spec.js b/app/javascript/dashboard/store/modules/specs/assignmentPolicies/actions.spec.js
new file mode 100644
index 000000000..1398f5959
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/specs/assignmentPolicies/actions.spec.js
@@ -0,0 +1,326 @@
+import axios from 'axios';
+import { actions } from '../../assignmentPolicies';
+import types from '../../../mutation-types';
+import assignmentPoliciesList, { camelCaseFixtures } from './fixtures';
+import camelcaseKeys from 'camelcase-keys';
+import snakecaseKeys from 'snakecase-keys';
+
+const commit = vi.fn();
+
+global.axios = axios;
+vi.mock('axios');
+vi.mock('camelcase-keys');
+vi.mock('snakecase-keys');
+vi.mock('../../../utils/api');
+
+describe('#actions', () => {
+  beforeEach(() => {
+    vi.clearAllMocks();
+  });
+
+  describe('#get', () => {
+    it('sends correct actions if API is success', async () => {
+      axios.get.mockResolvedValue({ data: assignmentPoliciesList });
+      camelcaseKeys.mockReturnValue(camelCaseFixtures);
+
+      await actions.get({ commit });
+
+      expect(camelcaseKeys).toHaveBeenCalledWith(assignmentPoliciesList);
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetching: true }],
+        [types.SET_ASSIGNMENT_POLICIES, camelCaseFixtures],
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetching: false }],
+      ]);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.get.mockRejectedValue({ message: 'Incorrect header' });
+
+      await actions.get({ commit });
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetching: true }],
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetching: false }],
+      ]);
+    });
+  });
+
+  describe('#show', () => {
+    it('sends correct actions if API is success', async () => {
+      const policyData = assignmentPoliciesList[0];
+      const camelCasedPolicy = camelCaseFixtures[0];
+
+      axios.get.mockResolvedValue({ data: policyData });
+      camelcaseKeys.mockReturnValue(camelCasedPolicy);
+
+      await actions.show({ commit }, 1);
+
+      expect(camelcaseKeys).toHaveBeenCalledWith(policyData);
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetchingItem: true }],
+        [types.SET_ASSIGNMENT_POLICY, camelCasedPolicy],
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetchingItem: false }],
+      ]);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.get.mockRejectedValue({ message: 'Not found' });
+
+      await actions.show({ commit }, 1);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetchingItem: true }],
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isFetchingItem: false }],
+      ]);
+    });
+  });
+
+  describe('#create', () => {
+    it('sends correct actions if API is success', async () => {
+      const newPolicy = assignmentPoliciesList[0];
+      const camelCasedData = camelCaseFixtures[0];
+      const snakeCasedPolicy = { assignment_order: 'round_robin' };
+
+      axios.post.mockResolvedValue({ data: newPolicy });
+      camelcaseKeys.mockReturnValue(camelCasedData);
+      snakecaseKeys.mockReturnValue(snakeCasedPolicy);
+
+      const result = await actions.create({ commit }, newPolicy);
+
+      expect(snakecaseKeys).toHaveBeenCalledWith(newPolicy);
+      expect(camelcaseKeys).toHaveBeenCalledWith(newPolicy);
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isCreating: true }],
+        [types.ADD_ASSIGNMENT_POLICY, camelCasedData],
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isCreating: false }],
+      ]);
+      expect(result).toEqual(newPolicy);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.post.mockRejectedValue(new Error('Validation error'));
+
+      await expect(actions.create({ commit }, {})).rejects.toThrow(Error);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isCreating: true }],
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isCreating: false }],
+      ]);
+    });
+  });
+
+  describe('#update', () => {
+    it('sends correct actions if API is success', async () => {
+      const updateParams = { id: 1, name: 'Updated Policy' };
+      const responseData = {
+        ...assignmentPoliciesList[0],
+        name: 'Updated Policy',
+      };
+      const camelCasedData = {
+        ...camelCaseFixtures[0],
+        name: 'Updated Policy',
+      };
+      const snakeCasedParams = { name: 'Updated Policy' };
+
+      axios.patch.mockResolvedValue({ data: responseData });
+      camelcaseKeys.mockReturnValue(camelCasedData);
+      snakecaseKeys.mockReturnValue(snakeCasedParams);
+
+      const result = await actions.update({ commit }, updateParams);
+
+      expect(snakecaseKeys).toHaveBeenCalledWith({ name: 'Updated Policy' });
+      expect(camelcaseKeys).toHaveBeenCalledWith(responseData);
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isUpdating: true }],
+        [types.EDIT_ASSIGNMENT_POLICY, camelCasedData],
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isUpdating: false }],
+      ]);
+      expect(result).toEqual(responseData);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.patch.mockRejectedValue(new Error('Validation error'));
+
+      await expect(
+        actions.update({ commit }, { id: 1, name: 'Test' })
+      ).rejects.toThrow(Error);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isUpdating: true }],
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isUpdating: false }],
+      ]);
+    });
+  });
+
+  describe('#delete', () => {
+    it('sends correct actions if API is success', async () => {
+      const policyId = 1;
+      axios.delete.mockResolvedValue({});
+
+      await actions.delete({ commit }, policyId);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isDeleting: true }],
+        [types.DELETE_ASSIGNMENT_POLICY, policyId],
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isDeleting: false }],
+      ]);
+    });
+
+    it('sends correct actions if API is error', async () => {
+      axios.delete.mockRejectedValue(new Error('Not found'));
+
+      await expect(actions.delete({ commit }, 1)).rejects.toThrow(Error);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isDeleting: true }],
+        [types.SET_ASSIGNMENT_POLICIES_UI_FLAG, { isDeleting: false }],
+      ]);
+    });
+  });
+
+  describe('#getInboxes', () => {
+    it('sends correct actions if API is success', async () => {
+      const policyId = 1;
+      const inboxData = {
+        inboxes: [
+          { id: 1, name: 'Support' },
+          { id: 2, name: 'Sales' },
+        ],
+      };
+      const camelCasedInboxes = [
+        { id: 1, name: 'Support' },
+        { id: 2, name: 'Sales' },
+      ];
+
+      axios.get.mockResolvedValue({ data: inboxData });
+      camelcaseKeys.mockReturnValue(camelCasedInboxes);
+
+      await actions.getInboxes({ commit }, policyId);
+
+      expect(camelcaseKeys).toHaveBeenCalledWith(inboxData.inboxes);
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isFetching: true }],
+        [
+          types.SET_ASSIGNMENT_POLICIES_INBOXES,
+          { policyId, inboxes: camelCasedInboxes },
+        ],
+        [types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isFetching: false }],
+      ]);
+    });
+
+    it('sends correct actions if API fails', async () => {
+      axios.get.mockRejectedValue(new Error('API Error'));
+
+      await expect(actions.getInboxes({ commit }, 1)).rejects.toThrow(Error);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isFetching: true }],
+        [types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isFetching: false }],
+      ]);
+    });
+  });
+
+  describe('#setInboxPolicy', () => {
+    it('sends correct actions if API is success', async () => {
+      const responseData = { success: true, policy_id: 2 };
+      const camelCasedData = { success: true, policyId: 2 };
+
+      axios.post.mockResolvedValue({ data: responseData });
+      camelcaseKeys.mockReturnValue(camelCasedData);
+
+      const result = await actions.setInboxPolicy(
+        { commit },
+        { inboxId: 1, policyId: 2 }
+      );
+
+      expect(camelcaseKeys).toHaveBeenCalledWith(responseData);
+      expect(commit.mock.calls).toEqual([
+        [types.ADD_ASSIGNMENT_POLICIES_INBOXES, camelCasedData],
+      ]);
+      expect(result).toEqual(responseData);
+    });
+
+    it('throws error if API fails', async () => {
+      axios.post.mockRejectedValue(new Error('API Error'));
+
+      await expect(
+        actions.setInboxPolicy({ commit }, { inboxId: 1, policyId: 2 })
+      ).rejects.toThrow(Error);
+    });
+  });
+
+  describe('#getInboxPolicy', () => {
+    it('returns camelCased response data if API is success', async () => {
+      const responseData = { policy_id: 1, name: 'Round Robin' };
+      const camelCasedData = { policyId: 1, name: 'Round Robin' };
+
+      axios.get.mockResolvedValue({ data: responseData });
+      camelcaseKeys.mockReturnValue(camelCasedData);
+
+      const result = await actions.getInboxPolicy({}, { inboxId: 1 });
+
+      expect(camelcaseKeys).toHaveBeenCalledWith(responseData);
+      expect(result).toEqual(camelCasedData);
+    });
+
+    it('throws error if API fails', async () => {
+      axios.get.mockRejectedValue(new Error('Not found'));
+
+      await expect(
+        actions.getInboxPolicy({}, { inboxId: 999 })
+      ).rejects.toThrow(Error);
+    });
+  });
+
+  describe('#updateInboxPolicy', () => {
+    it('commits EDIT_ASSIGNMENT_POLICY mutation', async () => {
+      const policy = { id: 1, name: 'Updated Policy' };
+
+      await actions.updateInboxPolicy({ commit }, { policy });
+
+      expect(commit.mock.calls).toEqual([
+        [types.EDIT_ASSIGNMENT_POLICY, policy],
+      ]);
+    });
+
+    it('throws error if commit fails', async () => {
+      commit.mockImplementation(() => {
+        throw new Error('Commit failed');
+      });
+
+      await expect(
+        actions.updateInboxPolicy({ commit }, { policy: {} })
+      ).rejects.toThrow(Error);
+    });
+  });
+
+  describe('#removeInboxPolicy', () => {
+    it('sends correct actions if API is success', async () => {
+      const policyId = 1;
+      const inboxId = 2;
+
+      axios.delete.mockResolvedValue({});
+
+      await actions.removeInboxPolicy({ commit }, { policyId, inboxId });
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isDeleting: true }],
+        [types.DELETE_ASSIGNMENT_POLICIES_INBOXES, { policyId, inboxId }],
+        [types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isDeleting: false }],
+      ]);
+    });
+
+    it('sends correct actions if API fails', async () => {
+      axios.delete.mockRejectedValue(new Error('Not found'));
+
+      await expect(
+        actions.removeInboxPolicy({ commit }, { policyId: 1, inboxId: 999 })
+      ).rejects.toThrow(Error);
+
+      expect(commit.mock.calls).toEqual([
+        [types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isDeleting: true }],
+        [types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG, { isDeleting: false }],
+      ]);
+    });
+  });
+});
diff --git a/app/javascript/dashboard/store/modules/specs/assignmentPolicies/fixtures.js b/app/javascript/dashboard/store/modules/specs/assignmentPolicies/fixtures.js
new file mode 100644
index 000000000..1b5ed25af
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/specs/assignmentPolicies/fixtures.js
@@ -0,0 +1,57 @@
+export default [
+  {
+    id: 1,
+    name: 'Round Robin Policy',
+    description: 'Distributes conversations evenly among agents',
+    assignment_order: 'round_robin',
+    conversation_priority: 'earliest_created',
+    fair_distribution_limit: 100,
+    fair_distribution_window: 3600,
+    enabled: true,
+    assigned_inbox_count: 3,
+    created_at: 1704110400,
+    updated_at: 1704110400,
+  },
+  {
+    id: 2,
+    name: 'Balanced Policy',
+    description: 'Assigns conversations based on agent capacity',
+    assignment_order: 'balanced',
+    conversation_priority: 'longest_waiting',
+    fair_distribution_limit: 50,
+    fair_distribution_window: 1800,
+    enabled: false,
+    assigned_inbox_count: 1,
+    created_at: 1704114000,
+    updated_at: 1704114000,
+  },
+];
+
+export const camelCaseFixtures = [
+  {
+    id: 1,
+    name: 'Round Robin Policy',
+    description: 'Distributes conversations evenly among agents',
+    assignmentOrder: 'round_robin',
+    conversationPriority: 'earliest_created',
+    fairDistributionLimit: 100,
+    fairDistributionWindow: 3600,
+    enabled: true,
+    assignedInboxCount: 3,
+    createdAt: 1704110400,
+    updatedAt: 1704110400,
+  },
+  {
+    id: 2,
+    name: 'Balanced Policy',
+    description: 'Assigns conversations based on agent capacity',
+    assignmentOrder: 'balanced',
+    conversationPriority: 'longest_waiting',
+    fairDistributionLimit: 50,
+    fairDistributionWindow: 1800,
+    enabled: false,
+    assignedInboxCount: 1,
+    createdAt: 1704114000,
+    updatedAt: 1704114000,
+  },
+];
diff --git a/app/javascript/dashboard/store/modules/specs/assignmentPolicies/getters.spec.js b/app/javascript/dashboard/store/modules/specs/assignmentPolicies/getters.spec.js
new file mode 100644
index 000000000..4fd1e7ad7
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/specs/assignmentPolicies/getters.spec.js
@@ -0,0 +1,51 @@
+import { getters } from '../../assignmentPolicies';
+import assignmentPoliciesList from './fixtures';
+
+describe('#getters', () => {
+  it('getAssignmentPolicies', () => {
+    const state = { records: assignmentPoliciesList };
+    expect(getters.getAssignmentPolicies(state)).toEqual(
+      assignmentPoliciesList
+    );
+  });
+
+  it('getUIFlags', () => {
+    const state = {
+      uiFlags: {
+        isFetching: true,
+        isFetchingItem: false,
+        isCreating: false,
+        isUpdating: false,
+        isDeleting: false,
+      },
+    };
+    expect(getters.getUIFlags(state)).toEqual({
+      isFetching: true,
+      isFetchingItem: false,
+      isCreating: false,
+      isUpdating: false,
+      isDeleting: false,
+    });
+  });
+
+  it('getInboxUiFlags', () => {
+    const state = {
+      inboxUiFlags: {
+        isFetching: false,
+        isDeleting: false,
+      },
+    };
+    expect(getters.getInboxUiFlags(state)).toEqual({
+      isFetching: false,
+      isDeleting: false,
+    });
+  });
+
+  it('getAssignmentPolicyById', () => {
+    const state = { records: assignmentPoliciesList };
+    expect(getters.getAssignmentPolicyById(state)(1)).toEqual(
+      assignmentPoliciesList[0]
+    );
+    expect(getters.getAssignmentPolicyById(state)(3)).toEqual({});
+  });
+});
diff --git a/app/javascript/dashboard/store/modules/specs/assignmentPolicies/mutations.spec.js b/app/javascript/dashboard/store/modules/specs/assignmentPolicies/mutations.spec.js
new file mode 100644
index 000000000..b3c029c57
--- /dev/null
+++ b/app/javascript/dashboard/store/modules/specs/assignmentPolicies/mutations.spec.js
@@ -0,0 +1,385 @@
+import { mutations } from '../../assignmentPolicies';
+import types from '../../../mutation-types';
+import assignmentPoliciesList from './fixtures';
+
+describe('#mutations', () => {
+  describe('#SET_ASSIGNMENT_POLICIES_UI_FLAG', () => {
+    it('sets single ui flag', () => {
+      const state = {
+        uiFlags: {
+          isFetching: false,
+          isCreating: false,
+        },
+      };
+
+      mutations[types.SET_ASSIGNMENT_POLICIES_UI_FLAG](state, {
+        isFetching: true,
+      });
+
+      expect(state.uiFlags).toEqual({
+        isFetching: true,
+        isCreating: false,
+      });
+    });
+
+    it('sets multiple ui flags', () => {
+      const state = {
+        uiFlags: {
+          isFetching: false,
+          isCreating: false,
+          isUpdating: false,
+        },
+      };
+
+      mutations[types.SET_ASSIGNMENT_POLICIES_UI_FLAG](state, {
+        isFetching: true,
+        isCreating: true,
+      });
+
+      expect(state.uiFlags).toEqual({
+        isFetching: true,
+        isCreating: true,
+        isUpdating: false,
+      });
+    });
+  });
+
+  describe('#SET_ASSIGNMENT_POLICIES', () => {
+    it('sets assignment policies records', () => {
+      const state = { records: [] };
+
+      mutations[types.SET_ASSIGNMENT_POLICIES](state, assignmentPoliciesList);
+
+      expect(state.records).toEqual(assignmentPoliciesList);
+    });
+
+    it('replaces existing records', () => {
+      const state = { records: [{ id: 999, name: 'Old Policy' }] };
+
+      mutations[types.SET_ASSIGNMENT_POLICIES](state, assignmentPoliciesList);
+
+      expect(state.records).toEqual(assignmentPoliciesList);
+    });
+  });
+
+  describe('#SET_ASSIGNMENT_POLICY', () => {
+    it('sets single assignment policy record', () => {
+      const state = { records: [] };
+
+      mutations[types.SET_ASSIGNMENT_POLICY](state, assignmentPoliciesList[0]);
+
+      expect(state.records).toEqual([assignmentPoliciesList[0]]);
+    });
+
+    it('replaces existing record', () => {
+      const state = { records: [{ id: 1, name: 'Old Policy' }] };
+
+      mutations[types.SET_ASSIGNMENT_POLICY](state, assignmentPoliciesList[0]);
+
+      expect(state.records).toEqual([assignmentPoliciesList[0]]);
+    });
+  });
+
+  describe('#ADD_ASSIGNMENT_POLICY', () => {
+    it('adds new policy to empty records', () => {
+      const state = { records: [] };
+
+      mutations[types.ADD_ASSIGNMENT_POLICY](state, assignmentPoliciesList[0]);
+
+      expect(state.records).toEqual([assignmentPoliciesList[0]]);
+    });
+
+    it('adds new policy to existing records', () => {
+      const state = { records: [assignmentPoliciesList[0]] };
+
+      mutations[types.ADD_ASSIGNMENT_POLICY](state, assignmentPoliciesList[1]);
+
+      expect(state.records).toEqual([
+        assignmentPoliciesList[0],
+        assignmentPoliciesList[1],
+      ]);
+    });
+  });
+
+  describe('#EDIT_ASSIGNMENT_POLICY', () => {
+    it('updates existing policy by id', () => {
+      const state = {
+        records: [
+          { ...assignmentPoliciesList[0] },
+          { ...assignmentPoliciesList[1] },
+        ],
+      };
+
+      const updatedPolicy = {
+        ...assignmentPoliciesList[0],
+        name: 'Updated Policy Name',
+        description: 'Updated Description',
+      };
+
+      mutations[types.EDIT_ASSIGNMENT_POLICY](state, updatedPolicy);
+
+      expect(state.records[0]).toEqual(updatedPolicy);
+      expect(state.records[1]).toEqual(assignmentPoliciesList[1]);
+    });
+
+    it('updates policy with camelCase properties', () => {
+      const camelCasePolicy = {
+        id: 1,
+        name: 'Camel Case Policy',
+        assignmentOrder: 'round_robin',
+        conversationPriority: 'earliest_created',
+      };
+
+      const state = {
+        records: [camelCasePolicy],
+      };
+
+      const updatedPolicy = {
+        ...camelCasePolicy,
+        name: 'Updated Camel Case',
+        assignmentOrder: 'balanced',
+      };
+
+      mutations[types.EDIT_ASSIGNMENT_POLICY](state, updatedPolicy);
+
+      expect(state.records[0]).toEqual(updatedPolicy);
+    });
+
+    it('does nothing if policy id not found', () => {
+      const state = {
+        records: [assignmentPoliciesList[0]],
+      };
+
+      const nonExistentPolicy = {
+        id: 999,
+        name: 'Non-existent',
+      };
+
+      const originalRecords = [...state.records];
+      mutations[types.EDIT_ASSIGNMENT_POLICY](state, nonExistentPolicy);
+
+      expect(state.records).toEqual(originalRecords);
+    });
+  });
+
+  describe('#DELETE_ASSIGNMENT_POLICY', () => {
+    it('deletes policy by id', () => {
+      const state = {
+        records: [assignmentPoliciesList[0], assignmentPoliciesList[1]],
+      };
+
+      mutations[types.DELETE_ASSIGNMENT_POLICY](state, 1);
+
+      expect(state.records).toEqual([assignmentPoliciesList[1]]);
+    });
+
+    it('does nothing if id not found', () => {
+      const state = {
+        records: [assignmentPoliciesList[0]],
+      };
+
+      mutations[types.DELETE_ASSIGNMENT_POLICY](state, 999);
+
+      expect(state.records).toEqual([assignmentPoliciesList[0]]);
+    });
+
+    it('handles empty records', () => {
+      const state = { records: [] };
+
+      mutations[types.DELETE_ASSIGNMENT_POLICY](state, 1);
+
+      expect(state.records).toEqual([]);
+    });
+  });
+
+  describe('#SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG', () => {
+    it('sets inbox ui flags', () => {
+      const state = {
+        inboxUiFlags: {
+          isFetching: false,
+        },
+      };
+
+      mutations[types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG](state, {
+        isFetching: true,
+      });
+
+      expect(state.inboxUiFlags).toEqual({
+        isFetching: true,
+      });
+    });
+
+    it('merges with existing flags', () => {
+      const state = {
+        inboxUiFlags: {
+          isFetching: false,
+          isLoading: true,
+        },
+      };
+
+      mutations[types.SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG](state, {
+        isFetching: true,
+      });
+
+      expect(state.inboxUiFlags).toEqual({
+        isFetching: true,
+        isLoading: true,
+      });
+    });
+  });
+
+  describe('#SET_ASSIGNMENT_POLICIES_INBOXES', () => {
+    it('sets inboxes for existing policy', () => {
+      const mockInboxes = [
+        { id: 1, name: 'Support Inbox' },
+        { id: 2, name: 'Sales Inbox' },
+      ];
+
+      const state = {
+        records: [
+          { id: 1, name: 'Policy 1', inboxes: [] },
+          { id: 2, name: 'Policy 2', inboxes: [] },
+        ],
+      };
+
+      mutations[types.SET_ASSIGNMENT_POLICIES_INBOXES](state, {
+        policyId: 1,
+        inboxes: mockInboxes,
+      });
+
+      expect(state.records[0].inboxes).toEqual(mockInboxes);
+      expect(state.records[1].inboxes).toEqual([]);
+    });
+
+    it('replaces existing inboxes', () => {
+      const oldInboxes = [{ id: 99, name: 'Old Inbox' }];
+      const newInboxes = [{ id: 1, name: 'New Inbox' }];
+
+      const state = {
+        records: [{ id: 1, name: 'Policy 1', inboxes: oldInboxes }],
+      };
+
+      mutations[types.SET_ASSIGNMENT_POLICIES_INBOXES](state, {
+        policyId: 1,
+        inboxes: newInboxes,
+      });
+
+      expect(state.records[0].inboxes).toEqual(newInboxes);
+    });
+
+    it('does nothing if policy not found', () => {
+      const state = {
+        records: [{ id: 1, name: 'Policy 1', inboxes: [] }],
+      };
+
+      const originalState = JSON.parse(JSON.stringify(state));
+
+      mutations[types.SET_ASSIGNMENT_POLICIES_INBOXES](state, {
+        policyId: 999,
+        inboxes: [{ id: 1, name: 'Test' }],
+      });
+
+      expect(state).toEqual(originalState);
+    });
+  });
+
+  describe('#DELETE_ASSIGNMENT_POLICIES_INBOXES', () => {
+    it('removes inbox from policy', () => {
+      const mockInboxes = [
+        { id: 1, name: 'Support Inbox' },
+        { id: 2, name: 'Sales Inbox' },
+        { id: 3, name: 'Marketing Inbox' },
+      ];
+
+      const state = {
+        records: [
+          { id: 1, name: 'Policy 1', inboxes: mockInboxes },
+          { id: 2, name: 'Policy 2', inboxes: [] },
+        ],
+      };
+
+      mutations[types.DELETE_ASSIGNMENT_POLICIES_INBOXES](state, {
+        policyId: 1,
+        inboxId: 2,
+      });
+
+      expect(state.records[0].inboxes).toEqual([
+        { id: 1, name: 'Support Inbox' },
+        { id: 3, name: 'Marketing Inbox' },
+      ]);
+      expect(state.records[1].inboxes).toEqual([]);
+    });
+
+    it('does nothing if policy not found', () => {
+      const state = {
+        records: [
+          { id: 1, name: 'Policy 1', inboxes: [{ id: 1, name: 'Test' }] },
+        ],
+      };
+
+      const originalState = JSON.parse(JSON.stringify(state));
+
+      mutations[types.DELETE_ASSIGNMENT_POLICIES_INBOXES](state, {
+        policyId: 999,
+        inboxId: 1,
+      });
+
+      expect(state).toEqual(originalState);
+    });
+
+    it('does nothing if inbox not found in policy', () => {
+      const mockInboxes = [{ id: 1, name: 'Support Inbox' }];
+
+      const state = {
+        records: [{ id: 1, name: 'Policy 1', inboxes: mockInboxes }],
+      };
+
+      mutations[types.DELETE_ASSIGNMENT_POLICIES_INBOXES](state, {
+        policyId: 1,
+        inboxId: 999,
+      });
+
+      expect(state.records[0].inboxes).toEqual(mockInboxes);
+    });
+
+    it('handles policy with no inboxes', () => {
+      const state = {
+        records: [{ id: 1, name: 'Policy 1' }],
+      };
+
+      mutations[types.DELETE_ASSIGNMENT_POLICIES_INBOXES](state, {
+        policyId: 1,
+        inboxId: 1,
+      });
+
+      expect(state.records[0]).toEqual({ id: 1, name: 'Policy 1' });
+    });
+  });
+
+  describe('#ADD_ASSIGNMENT_POLICIES_INBOXES', () => {
+    it('updates policy attributes using MutationHelpers.updateAttributes', () => {
+      const state = {
+        records: [
+          { id: 1, name: 'Policy 1', assignedInboxCount: 2 },
+          { id: 2, name: 'Policy 2', assignedInboxCount: 1 },
+        ],
+      };
+
+      const updatedPolicy = {
+        id: 1,
+        name: 'Policy 1',
+        assignedInboxCount: 3,
+        inboxes: [{ id: 1, name: 'New Inbox' }],
+      };
+
+      mutations[types.ADD_ASSIGNMENT_POLICIES_INBOXES](state, updatedPolicy);
+
+      expect(state.records[0]).toEqual(updatedPolicy);
+      expect(state.records[1]).toEqual({
+        id: 2,
+        name: 'Policy 2',
+        assignedInboxCount: 1,
+      });
+    });
+  });
+});
diff --git a/app/javascript/dashboard/store/mutation-types.js b/app/javascript/dashboard/store/mutation-types.js
index a63fec2d1..4f361e140 100644
--- a/app/javascript/dashboard/store/mutation-types.js
+++ b/app/javascript/dashboard/store/mutation-types.js
@@ -348,4 +348,34 @@ export default {
   SET_TEAM_CONVERSATION_METRIC: 'SET_TEAM_CONVERSATION_METRIC',
   TOGGLE_TEAM_CONVERSATION_METRIC_LOADING:
     'TOGGLE_TEAM_CONVERSATION_METRIC_LOADING',
+
+  // Assignment Policies
+  SET_ASSIGNMENT_POLICIES_UI_FLAG: 'SET_ASSIGNMENT_POLICIES_UI_FLAG',
+  SET_ASSIGNMENT_POLICIES: 'SET_ASSIGNMENT_POLICIES',
+  SET_ASSIGNMENT_POLICY: 'SET_ASSIGNMENT_POLICY',
+  ADD_ASSIGNMENT_POLICY: 'ADD_ASSIGNMENT_POLICY',
+  EDIT_ASSIGNMENT_POLICY: 'EDIT_ASSIGNMENT_POLICY',
+  DELETE_ASSIGNMENT_POLICY: 'DELETE_ASSIGNMENT_POLICY',
+  SET_ASSIGNMENT_POLICIES_INBOXES: 'SET_ASSIGNMENT_POLICIES_INBOXES',
+  SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG:
+    'SET_ASSIGNMENT_POLICIES_INBOXES_UI_FLAG',
+  DELETE_ASSIGNMENT_POLICIES_INBOXES: 'DELETE_ASSIGNMENT_POLICIES_INBOXES',
+  ADD_ASSIGNMENT_POLICIES_INBOXES: 'ADD_ASSIGNMENT_POLICIES_INBOXES',
+
+  // Agent Capacity Policies
+  SET_AGENT_CAPACITY_POLICIES_UI_FLAG: 'SET_AGENT_CAPACITY_POLICIES_UI_FLAG',
+  SET_AGENT_CAPACITY_POLICIES: 'SET_AGENT_CAPACITY_POLICIES',
+  SET_AGENT_CAPACITY_POLICY: 'SET_AGENT_CAPACITY_POLICY',
+  ADD_AGENT_CAPACITY_POLICY: 'ADD_AGENT_CAPACITY_POLICY',
+  EDIT_AGENT_CAPACITY_POLICY: 'EDIT_AGENT_CAPACITY_POLICY',
+  DELETE_AGENT_CAPACITY_POLICY: 'DELETE_AGENT_CAPACITY_POLICY',
+  SET_AGENT_CAPACITY_POLICIES_USERS: 'SET_AGENT_CAPACITY_POLICIES_USERS',
+  SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG:
+    'SET_AGENT_CAPACITY_POLICIES_USERS_UI_FLAG',
+  ADD_AGENT_CAPACITY_POLICIES_USERS: 'ADD_AGENT_CAPACITY_POLICIES_USERS',
+  DELETE_AGENT_CAPACITY_POLICIES_USERS: 'DELETE_AGENT_CAPACITY_POLICIES_USERS',
+  SET_AGENT_CAPACITY_POLICIES_INBOXES: 'SET_AGENT_CAPACITY_POLICIES_INBOXES',
+  EDIT_AGENT_CAPACITY_POLICIES_INBOXES: 'EDIT_AGENT_CAPACITY_POLICIES_INBOXES',
+  DELETE_AGENT_CAPACITY_POLICIES_INBOXES:
+    'DELETE_AGENT_CAPACITY_POLICIES_INBOXES',
 };
diff --git a/app/javascript/histoire.setup.ts b/app/javascript/histoire.setup.ts
index 7642da78d..1c80a9f85 100644
--- a/app/javascript/histoire.setup.ts
+++ b/app/javascript/histoire.setup.ts
@@ -1,6 +1,7 @@
 import './design-system/histoire.scss';
 import { defineSetupVue3 } from '@histoire/plugin-vue';
-import i18nMessages from 'dashboard/i18n';
+import dashboardI18n from 'dashboard/i18n';
+import widgetI18n from 'widget/i18n';
 import { createI18n } from 'vue-i18n';
 import { vResizeObserver } from '@vueuse/components';
 import store from 'dashboard/store';
@@ -9,10 +10,30 @@ import VueDOMPurifyHTML from 'vue-dompurify-html';
 import { domPurifyConfig } from 'shared/helpers/HTMLSanitizer.js';
 import { directive as onClickaway } from 'vue3-click-away';
 
+function mergeMessages(...sources) {
+  return sources.reduce((acc, src) => {
+    Object.keys(src).forEach(key => {
+      if (
+        acc[key] &&
+        typeof acc[key] === 'object' &&
+        typeof src[key] === 'object'
+      ) {
+        acc[key] = mergeMessages(acc[key], src[key]);
+      } else {
+        acc[key] = src[key];
+      }
+    });
+    return acc;
+  }, {});
+}
+
 const i18n = createI18n({
   legacy: false, // https://github.com/intlify/vue-i18n/issues/1902
   locale: 'en',
-  messages: i18nMessages,
+  messages: mergeMessages(
+    structuredClone(dashboardI18n),
+    structuredClone(widgetI18n)
+  ),
 });
 
 export const setupVue3 = defineSetupVue3(({ app }) => {
diff --git a/app/javascript/sdk/IFrameHelper.js b/app/javascript/sdk/IFrameHelper.js
index 25f90912d..3ab1ba1f5 100644
--- a/app/javascript/sdk/IFrameHelper.js
+++ b/app/javascript/sdk/IFrameHelper.js
@@ -50,35 +50,11 @@ const updateCampaignReadStatus = baseDomain => {
   });
 };
 
-const sanitizeURL = url => {
-  if (url === '') return '';
-
-  try {
-    // any invalid url will not be accepted
-    // example - JaVaScRiP%0at:alert(document.domain)"
-    // this has an obfuscated javascript protocol
-    const parsedURL = new URL(url);
-
-    // filter out dangerous protocols like `javascript`, `data`, `vbscript`
-    if (!['https', 'http'].includes(parsedURL.protocol)) {
-      throw new Error('Invalid Protocol');
-    }
-  } catch (e) {
-    // eslint-disable-next-line no-console
-    console.error('Invalid URL', e);
-  }
-
-  return 'about:blank'; // blank page URL
-};
-
 export const IFrameHelper = {
   getUrl({ baseUrl, websiteToken }) {
-    baseUrl = sanitizeURL(baseUrl);
     return `${baseUrl}/widget?website_token=${websiteToken}`;
   },
   createFrame: ({ baseUrl, websiteToken }) => {
-    baseUrl = sanitizeURL(baseUrl);
-
     if (IFrameHelper.getAppFrame()) {
       return;
     }
@@ -126,12 +102,10 @@ export const IFrameHelper = {
     window.onmessage = e => {
       if (
         typeof e.data !== 'string' ||
-        e.data.indexOf('chatwoot-widget:') !== 0 ||
-        e.origin !== window.location.origin
+        e.data.indexOf('chatwoot-widget:') !== 0
       ) {
         return;
       }
-
       const message = JSON.parse(e.data.replace('chatwoot-widget:', ''));
       if (typeof IFrameHelper.events[message.event] === 'function') {
         IFrameHelper.events[message.event](message);
@@ -166,9 +140,7 @@ export const IFrameHelper = {
   },
 
   setupAudioListeners: () => {
-    let { baseUrl = '' } = window.$chatwoot;
-    baseUrl = sanitizeURL(baseUrl);
-
+    const { baseUrl = '' } = window.$chatwoot;
     getAlertAudio(baseUrl, { type: 'widget', alertTone: 'ding' }).then(() =>
       initOnEvents.forEach(event => {
         document.removeEventListener(
@@ -262,7 +234,6 @@ export const IFrameHelper = {
     },
 
     popoutChatWindow: ({ baseUrl, websiteToken, locale }) => {
-      baseUrl = sanitizeURL(baseUrl);
       const cwCookie = Cookies.get('cw_conversation');
       window.$chatwoot.toggle('close');
       popoutChatWindow(baseUrl, websiteToken, locale, cwCookie);
diff --git a/app/javascript/shared/components/Branding.vue b/app/javascript/shared/components/Branding.vue
index 9ca976d80..2f1a8d5d0 100644
--- a/app/javascript/shared/components/Branding.vue
+++ b/app/javascript/shared/components/Branding.vue
@@ -33,13 +33,15 @@ export default {
     brandRedirectURL() {
       try {
         const referrerHost = this.$store.getters['appConfig/getReferrerHost'];
-        const baseURL = `${this.globalConfig.widgetBrandURL}?utm_source=${
-          referrerHost ? 'widget_branding' : 'survey_branding'
-        }`;
+        const url = new URL(this.globalConfig.widgetBrandURL);
         if (referrerHost) {
-          return `${baseURL}&utm_referrer=${referrerHost}`;
+          url.searchParams.set('utm_source', referrerHost);
+          url.searchParams.set('utm_medium', 'widget');
+        } else {
+          url.searchParams.set('utm_medium', 'survey');
         }
-        return baseURL;
+        url.searchParams.set('utm_campaign', 'branding');
+        return url.toString();
       } catch (e) {
         // Suppressing the error as getter is not defined in some cases
       }
diff --git a/app/javascript/shared/constants/messages.js b/app/javascript/shared/constants/messages.js
index 7b7b4f331..47c1e8651 100644
--- a/app/javascript/shared/constants/messages.js
+++ b/app/javascript/shared/constants/messages.js
@@ -36,7 +36,6 @@ export const CONVERSATION_PRIORITY_ORDER = {
 
 // Size in mega bytes
 export const MAXIMUM_FILE_UPLOAD_SIZE = 40;
-export const MAXIMUM_FILE_UPLOAD_SIZE_TWILIO_SMS_CHANNEL = 5;
 
 export const ALLOWED_FILE_TYPES =
   'image/*,' +
@@ -50,18 +49,6 @@ export const ALLOWED_FILE_TYPES =
   'application/vnd.openxmlformats-officedocument.presentationml.presentation, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,' +
   'application/vnd.openxmlformats-officedocument.wordprocessingml.document,';
 
-export const ALLOWED_FILE_TYPES_FOR_TWILIO_WHATSAPP =
-  'image/png, image/jpeg,' +
-  'audio/mpeg, audio/opus, audio/ogg, audio/amr,' +
-  'video/mp4,' +
-  'application/pdf,';
-// https://developers.line.biz/en/reference/messaging-api/#image-message, https://developers.line.biz/en/reference/messaging-api/#video-message
-export const ALLOWED_FILE_TYPES_FOR_LINE = 'image/png, image/jpeg,video/mp4';
-
-// https://developers.facebook.com/docs/instagram-platform/instagram-api-with-instagram-login/messaging-api#requirements
-export const ALLOWED_FILE_TYPES_FOR_INSTAGRAM =
-  'image/png, image/jpeg, video/mp4, video/mov, video/webm';
-
 export const CSAT_RATINGS = [
   {
     key: 'disappointed',
@@ -175,3 +162,9 @@ export const ATTACHMENT_ICONS = {
   location: 'location',
   fallback: 'link',
 };
+
+export const TWILIO_CONTENT_TEMPLATE_TYPES = {
+  TEXT: 'text',
+  MEDIA: 'media',
+  QUICK_REPLY: 'quick_reply',
+};
diff --git a/app/javascript/shared/helpers/clipboard.js b/app/javascript/shared/helpers/clipboard.js
index dbadd4037..3b66c39ac 100644
--- a/app/javascript/shared/helpers/clipboard.js
+++ b/app/javascript/shared/helpers/clipboard.js
@@ -2,13 +2,37 @@
  * Writes a text string to the system clipboard.
  *
  * @async
- * @param {string} text text to be written to the clipboard
+ * @param {string} data text to be written to the clipboard
  * @throws {Error} unable to copy text to clipboard
  */
-export const copyTextToClipboard = async text => {
+export const copyTextToClipboard = async data => {
   try {
+    const text =
+      typeof data === 'object' && data !== null
+        ? JSON.stringify(data, null, 2)
+        : String(data ?? '');
+
     await navigator.clipboard.writeText(text);
   } catch (error) {
     throw new Error(`Unable to copy text to clipboard: ${error.message}`);
   }
 };
+
+/**
+ * Handles OTP paste events by extracting numeric digits from clipboard data.
+ *
+ * @param {ClipboardEvent} event - The paste event from the clipboard
+ * @param {number} maxLength - Maximum number of digits to extract (default: 6)
+ * @returns {string|null} - Extracted numeric string or null if invalid
+ */
+export const handleOtpPaste = (event, maxLength = 6) => {
+  if (!event?.clipboardData) return null;
+
+  const pastedData = event.clipboardData
+    .getData('text')
+    .replace(/\D/g, '') // Remove all non-digit characters
+    .slice(0, maxLength); // Limit to maxLength digits
+
+  // Only return if we have the exact expected length
+  return pastedData.length === maxLength ? pastedData : null;
+};
diff --git a/app/javascript/shared/helpers/documentHelper.js b/app/javascript/shared/helpers/documentHelper.js
new file mode 100644
index 000000000..f050ad54d
--- /dev/null
+++ b/app/javascript/shared/helpers/documentHelper.js
@@ -0,0 +1,38 @@
+/**
+ * Document Helper - utilities for document display and formatting
+ */
+
+// Constants for document processing
+const PDF_PREFIX = 'PDF:';
+const TIMESTAMP_PATTERN = /_\d{14}(?=\.pdf$)/; // Format: _YYYYMMDDHHMMSS before .pdf extension
+
+/**
+ * Checks if a document is a PDF based on its external link
+ * @param {string} externalLink - The external link string
+ * @returns {boolean} True if the document is a PDF
+ */
+export const isPdfDocument = externalLink => {
+  if (!externalLink) return false;
+  return externalLink.startsWith(PDF_PREFIX);
+};
+
+/**
+ * Formats the display link for documents
+ * For PDF documents: removes 'PDF:' prefix and timestamp suffix
+ * For regular URLs: returns as-is
+ *
+ * @param {string} externalLink - The external link string
+ * @returns {string} Formatted display link
+ */
+export const formatDocumentLink = externalLink => {
+  if (!externalLink) return '';
+
+  if (isPdfDocument(externalLink)) {
+    // Remove 'PDF:' prefix
+    const fullName = externalLink.substring(PDF_PREFIX.length);
+    // Remove timestamp suffix if present
+    return fullName.replace(TIMESTAMP_PATTERN, '');
+  }
+
+  return externalLink;
+};
diff --git a/app/javascript/shared/helpers/specs/clipboard.spec.js b/app/javascript/shared/helpers/specs/clipboard.spec.js
new file mode 100644
index 000000000..a169e0939
--- /dev/null
+++ b/app/javascript/shared/helpers/specs/clipboard.spec.js
@@ -0,0 +1,284 @@
+import { copyTextToClipboard, handleOtpPaste } from '../clipboard';
+
+const mockWriteText = vi.fn();
+Object.assign(navigator, {
+  clipboard: {
+    writeText: mockWriteText,
+  },
+});
+
+describe('copyTextToClipboard', () => {
+  beforeEach(() => {
+    vi.clearAllMocks();
+  });
+
+  describe('with string input', () => {
+    it('copies plain text string to clipboard', async () => {
+      const text = 'Hello World';
+      await copyTextToClipboard(text);
+
+      expect(mockWriteText).toHaveBeenCalledWith('Hello World');
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+
+    it('copies empty string to clipboard', async () => {
+      const text = '';
+      await copyTextToClipboard(text);
+
+      expect(mockWriteText).toHaveBeenCalledWith('');
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+  });
+
+  describe('with number input', () => {
+    it('converts number to string', async () => {
+      await copyTextToClipboard(42);
+
+      expect(mockWriteText).toHaveBeenCalledWith('42');
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+
+    it('converts zero to string', async () => {
+      await copyTextToClipboard(0);
+
+      expect(mockWriteText).toHaveBeenCalledWith('0');
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+  });
+
+  describe('with boolean input', () => {
+    it('converts true to string', async () => {
+      await copyTextToClipboard(true);
+
+      expect(mockWriteText).toHaveBeenCalledWith('true');
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+
+    it('converts false to string', async () => {
+      await copyTextToClipboard(false);
+
+      expect(mockWriteText).toHaveBeenCalledWith('false');
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+  });
+
+  describe('with null/undefined input', () => {
+    it('converts null to empty string', async () => {
+      await copyTextToClipboard(null);
+
+      expect(mockWriteText).toHaveBeenCalledWith('');
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+
+    it('converts undefined to empty string', async () => {
+      await copyTextToClipboard(undefined);
+
+      expect(mockWriteText).toHaveBeenCalledWith('');
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+  });
+
+  describe('with object input', () => {
+    it('stringifies simple object with proper formatting', async () => {
+      const obj = { name: 'John', age: 30 };
+      await copyTextToClipboard(obj);
+
+      const expectedJson = JSON.stringify(obj, null, 2);
+      expect(mockWriteText).toHaveBeenCalledWith(expectedJson);
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+
+    it('stringifies nested object with proper formatting', async () => {
+      const nestedObj = {
+        severity: {
+          user_id: 1181505,
+          user_name: 'test',
+          server_name: '[1253]test1253',
+        },
+      };
+      await copyTextToClipboard(nestedObj);
+
+      const expectedJson = JSON.stringify(nestedObj, null, 2);
+      expect(mockWriteText).toHaveBeenCalledWith(expectedJson);
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+
+    it('stringifies array with proper formatting', async () => {
+      const arr = [1, 2, { name: 'test' }];
+      await copyTextToClipboard(arr);
+
+      const expectedJson = JSON.stringify(arr, null, 2);
+      expect(mockWriteText).toHaveBeenCalledWith(expectedJson);
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+
+    it('stringifies empty object', async () => {
+      const obj = {};
+      await copyTextToClipboard(obj);
+
+      expect(mockWriteText).toHaveBeenCalledWith('{}');
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+
+    it('stringifies empty array', async () => {
+      const arr = [];
+      await copyTextToClipboard(arr);
+
+      expect(mockWriteText).toHaveBeenCalledWith('[]');
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+  });
+
+  describe('error handling', () => {
+    it('throws error when clipboard API fails', async () => {
+      const error = new Error('Clipboard access denied');
+      mockWriteText.mockRejectedValueOnce(error);
+
+      await expect(copyTextToClipboard('test')).rejects.toThrow(
+        'Unable to copy text to clipboard: Clipboard access denied'
+      );
+    });
+
+    it('handles clipboard API not available', async () => {
+      // Temporarily remove clipboard API
+      const originalClipboard = navigator.clipboard;
+      delete navigator.clipboard;
+
+      await expect(copyTextToClipboard('test')).rejects.toThrow(
+        'Unable to copy text to clipboard:'
+      );
+
+      // Restore clipboard API
+      navigator.clipboard = originalClipboard;
+    });
+  });
+
+  describe('edge cases', () => {
+    it('handles Date objects', async () => {
+      const date = new Date('2023-01-01T00:00:00.000Z');
+      await copyTextToClipboard(date);
+
+      const expectedJson = JSON.stringify(date, null, 2);
+      expect(mockWriteText).toHaveBeenCalledWith(expectedJson);
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+
+    it('handles functions by converting to string', async () => {
+      const func = () => 'test';
+      await copyTextToClipboard(func);
+
+      expect(mockWriteText).toHaveBeenCalledWith(func.toString());
+      expect(mockWriteText).toHaveBeenCalledTimes(1);
+    });
+  });
+});
+
+describe('handleOtpPaste', () => {
+  // Helper function to create mock clipboard event
+  const createMockPasteEvent = text => ({
+    clipboardData: {
+      getData: vi.fn().mockReturnValue(text),
+    },
+  });
+
+  describe('valid OTP paste scenarios', () => {
+    it('extracts 6-digit OTP from clean numeric string', () => {
+      const event = createMockPasteEvent('123456');
+      const result = handleOtpPaste(event);
+
+      expect(result).toBe('123456');
+      expect(event.clipboardData.getData).toHaveBeenCalledWith('text');
+    });
+
+    it('extracts 6-digit OTP from string with spaces', () => {
+      const event = createMockPasteEvent('1 2 3 4 5 6');
+      const result = handleOtpPaste(event);
+
+      expect(result).toBe('123456');
+    });
+
+    it('extracts 6-digit OTP from string with dashes', () => {
+      const event = createMockPasteEvent('123-456');
+      const result = handleOtpPaste(event);
+
+      expect(result).toBe('123456');
+    });
+
+    it('handles negative numbers by extracting digits only', () => {
+      const event = createMockPasteEvent('-123456');
+      const result = handleOtpPaste(event);
+
+      expect(result).toBe('123456');
+    });
+
+    it('handles decimal numbers by extracting digits only', () => {
+      const event = createMockPasteEvent('123.456');
+      const result = handleOtpPaste(event);
+
+      expect(result).toBe('123456');
+    });
+
+    it('extracts 6-digit OTP from mixed alphanumeric string', () => {
+      const event = createMockPasteEvent('Your code is: 987654');
+      const result = handleOtpPaste(event);
+
+      expect(result).toBe('987654');
+    });
+
+    it('extracts first 6 digits when more than 6 digits present', () => {
+      const event = createMockPasteEvent('12345678901234');
+      const result = handleOtpPaste(event);
+
+      expect(result).toBe('123456');
+    });
+
+    it('handles custom maxLength parameter', () => {
+      const event = createMockPasteEvent('12345678');
+      const result = handleOtpPaste(event, 8);
+
+      expect(result).toBe('12345678');
+    });
+
+    it('extracts 4-digit OTP with custom maxLength', () => {
+      const event = createMockPasteEvent('Your PIN: 9876');
+      const result = handleOtpPaste(event, 4);
+
+      expect(result).toBe('9876');
+    });
+  });
+
+  describe('invalid OTP paste scenarios', () => {
+    it('returns null for insufficient digits', () => {
+      const event = createMockPasteEvent('12345');
+      const result = handleOtpPaste(event);
+
+      expect(result).toBeNull();
+    });
+
+    it('returns null for text with no digits', () => {
+      const event = createMockPasteEvent('Hello World');
+      const result = handleOtpPaste(event);
+
+      expect(result).toBeNull();
+    });
+
+    it('returns null for empty string', () => {
+      const event = createMockPasteEvent('');
+      const result = handleOtpPaste(event);
+
+      expect(result).toBeNull();
+    });
+
+    it('returns null when event is null', () => {
+      const result = handleOtpPaste(null);
+
+      expect(result).toBeNull();
+    });
+
+    it('returns null when event is undefined', () => {
+      const result = handleOtpPaste(undefined);
+
+      expect(result).toBeNull();
+    });
+  });
+});
diff --git a/app/javascript/shared/helpers/specs/documentHelper.spec.js b/app/javascript/shared/helpers/specs/documentHelper.spec.js
new file mode 100644
index 000000000..64baf7069
--- /dev/null
+++ b/app/javascript/shared/helpers/specs/documentHelper.spec.js
@@ -0,0 +1,111 @@
+import {
+  isPdfDocument,
+  formatDocumentLink,
+} from 'shared/helpers/documentHelper';
+
+describe('documentHelper', () => {
+  describe('#isPdfDocument', () => {
+    it('returns true for PDF documents', () => {
+      expect(isPdfDocument('PDF:document.pdf')).toBe(true);
+      expect(isPdfDocument('PDF:my-file_20241227123045.pdf')).toBe(true);
+      expect(isPdfDocument('PDF:report with spaces_20241227123045.pdf')).toBe(
+        true
+      );
+    });
+
+    it('returns false for regular URLs', () => {
+      expect(isPdfDocument('https://example.com')).toBe(false);
+      expect(isPdfDocument('http://docs.example.com/file.pdf')).toBe(false);
+      expect(isPdfDocument('ftp://files.example.com/document.pdf')).toBe(false);
+    });
+
+    it('returns false for empty or null values', () => {
+      expect(isPdfDocument('')).toBe(false);
+      expect(isPdfDocument(null)).toBe(false);
+      expect(isPdfDocument(undefined)).toBe(false);
+    });
+
+    it('returns false for strings that contain PDF but do not start with PDF:', () => {
+      expect(isPdfDocument('document PDF:file.pdf')).toBe(false);
+      expect(isPdfDocument('My PDF:file.pdf')).toBe(false);
+    });
+  });
+
+  describe('#formatDocumentLink', () => {
+    describe('PDF documents', () => {
+      it('removes PDF: prefix from PDF documents', () => {
+        expect(formatDocumentLink('PDF:document.pdf')).toBe('document.pdf');
+        expect(formatDocumentLink('PDF:my-file.pdf')).toBe('my-file.pdf');
+      });
+
+      it('removes timestamp suffix from PDF documents', () => {
+        expect(formatDocumentLink('PDF:document_20241227123045.pdf')).toBe(
+          'document.pdf'
+        );
+        expect(formatDocumentLink('PDF:report_20231215094530.pdf')).toBe(
+          'report.pdf'
+        );
+      });
+
+      it('handles PDF documents with spaces in filename', () => {
+        expect(formatDocumentLink('PDF:my document_20241227123045.pdf')).toBe(
+          'my document.pdf'
+        );
+        expect(
+          formatDocumentLink('PDF:Annual Report 2024_20241227123045.pdf')
+        ).toBe('Annual Report 2024.pdf');
+      });
+
+      it('handles PDF documents without timestamp suffix', () => {
+        expect(formatDocumentLink('PDF:document.pdf')).toBe('document.pdf');
+        expect(formatDocumentLink('PDF:simple-file.pdf')).toBe(
+          'simple-file.pdf'
+        );
+      });
+
+      it('handles PDF documents with partial timestamp patterns', () => {
+        expect(formatDocumentLink('PDF:document_202412.pdf')).toBe(
+          'document_202412.pdf'
+        );
+        expect(formatDocumentLink('PDF:file_123.pdf')).toBe('file_123.pdf');
+      });
+
+      it('handles edge cases with timestamp pattern', () => {
+        expect(
+          formatDocumentLink('PDF:doc_20241227123045_final_20241227123045.pdf')
+        ).toBe('doc_20241227123045_final.pdf');
+      });
+    });
+
+    describe('Regular URLs', () => {
+      it('returns regular URLs unchanged', () => {
+        expect(formatDocumentLink('https://example.com')).toBe(
+          'https://example.com'
+        );
+        expect(formatDocumentLink('http://docs.example.com/api')).toBe(
+          'http://docs.example.com/api'
+        );
+        expect(formatDocumentLink('https://github.com/user/repo')).toBe(
+          'https://github.com/user/repo'
+        );
+      });
+
+      it('handles URLs with query parameters', () => {
+        expect(formatDocumentLink('https://example.com?param=value')).toBe(
+          'https://example.com?param=value'
+        );
+        expect(
+          formatDocumentLink(
+            'https://api.example.com/docs?version=v1&format=json'
+          )
+        ).toBe('https://api.example.com/docs?version=v1&format=json');
+      });
+
+      it('handles URLs with fragments', () => {
+        expect(formatDocumentLink('https://example.com/docs#section1')).toBe(
+          'https://example.com/docs#section1'
+        );
+      });
+    });
+  });
+});
diff --git a/app/javascript/shared/helpers/specs/timeHelper.spec.js b/app/javascript/shared/helpers/specs/timeHelper.spec.js
index 13d04568f..e7a4e025f 100644
--- a/app/javascript/shared/helpers/specs/timeHelper.spec.js
+++ b/app/javascript/shared/helpers/specs/timeHelper.spec.js
@@ -4,6 +4,8 @@ import {
   dynamicTime,
   dateFormat,
   shortTimestamp,
+  getDayDifferenceFromNow,
+  hasOneDayPassed,
 } from 'shared/helpers/timeHelper';
 
 beforeEach(() => {
@@ -90,3 +92,148 @@ describe('#shortTimestamp', () => {
     expect(shortTimestamp('4 years ago', true)).toEqual('4y ago');
   });
 });
+
+describe('#getDayDifferenceFromNow', () => {
+  it('returns 0 for timestamps from today', () => {
+    // Mock current date: May 5, 2023
+    const now = new Date(Date.UTC(2023, 4, 5, 12, 0, 0)); // 12:00 PM
+    const todayTimestamp = Math.floor(now.getTime() / 1000); // Same day
+
+    expect(getDayDifferenceFromNow(now, todayTimestamp)).toEqual(0);
+  });
+
+  it('returns 2 for timestamps from 2 days ago', () => {
+    const now = new Date(Date.UTC(2023, 4, 5, 12, 0, 0)); // May 5, 2023
+    const twoDaysAgoTimestamp = Math.floor(
+      new Date(Date.UTC(2023, 4, 3, 10, 0, 0)).getTime() / 1000
+    ); // May 3, 2023
+
+    expect(getDayDifferenceFromNow(now, twoDaysAgoTimestamp)).toEqual(2);
+  });
+
+  it('returns 7 for timestamps from a week ago', () => {
+    const now = new Date(Date.UTC(2023, 4, 5, 12, 0, 0)); // May 5, 2023
+    const weekAgoTimestamp = Math.floor(
+      new Date(Date.UTC(2023, 3, 28, 8, 0, 0)).getTime() / 1000
+    ); // April 28, 2023
+
+    expect(getDayDifferenceFromNow(now, weekAgoTimestamp)).toEqual(7);
+  });
+
+  it('returns 30 for timestamps from a month ago', () => {
+    const now = new Date(Date.UTC(2023, 4, 5, 12, 0, 0)); // May 5, 2023
+    const monthAgoTimestamp = Math.floor(
+      new Date(Date.UTC(2023, 3, 5, 12, 0, 0)).getTime() / 1000
+    ); // April 5, 2023
+
+    expect(getDayDifferenceFromNow(now, monthAgoTimestamp)).toEqual(30);
+  });
+
+  it('handles edge case with different times on same day', () => {
+    const now = new Date(Date.UTC(2023, 4, 5, 23, 59, 59)); // May 5, 2023 11:59:59 PM
+    const morningTimestamp = Math.floor(
+      new Date(Date.UTC(2023, 4, 5, 0, 0, 1)).getTime() / 1000
+    ); // May 5, 2023 12:00:01 AM
+
+    expect(getDayDifferenceFromNow(now, morningTimestamp)).toEqual(0);
+  });
+
+  it('handles cross-month boundaries correctly', () => {
+    const now = new Date(Date.UTC(2023, 4, 1, 12, 0, 0)); // May 1, 2023
+    const lastMonthTimestamp = Math.floor(
+      new Date(Date.UTC(2023, 3, 30, 12, 0, 0)).getTime() / 1000
+    ); // April 30, 2023
+
+    expect(getDayDifferenceFromNow(now, lastMonthTimestamp)).toEqual(1);
+  });
+
+  it('handles cross-year boundaries correctly', () => {
+    const now = new Date(Date.UTC(2023, 0, 2, 12, 0, 0)); // January 2, 2023
+    const lastYearTimestamp = Math.floor(
+      new Date(Date.UTC(2022, 11, 31, 12, 0, 0)).getTime() / 1000
+    ); // December 31, 2022
+
+    expect(getDayDifferenceFromNow(now, lastYearTimestamp)).toEqual(2);
+  });
+});
+
+describe('#hasOneDayPassed', () => {
+  beforeEach(() => {
+    // Mock current date: May 5, 2023, 12:00 PM UTC (1683288000)
+    const mockDate = new Date(1683288000 * 1000);
+    vi.setSystemTime(mockDate);
+  });
+
+  it('returns false for timestamps from today', () => {
+    // Same day, different time - May 5, 2023 8:00 AM UTC
+    const todayTimestamp = 1683273600;
+
+    expect(hasOneDayPassed(todayTimestamp)).toBe(false);
+  });
+
+  it('returns false for timestamps from yesterday (less than 24 hours)', () => {
+    // Yesterday but less than 24 hours ago - May 4, 2023 6:00 PM UTC (18 hours ago)
+    const yesterdayTimestamp = 1683230400;
+
+    expect(hasOneDayPassed(yesterdayTimestamp)).toBe(false);
+  });
+
+  it('returns true for timestamps from exactly 1 day ago', () => {
+    // Exactly 24 hours ago - May 4, 2023 12:00 PM UTC
+    const oneDayAgoTimestamp = 1683201600;
+
+    expect(hasOneDayPassed(oneDayAgoTimestamp)).toBe(true);
+  });
+
+  it('returns true for timestamps from more than 1 day ago', () => {
+    // 2 days ago - May 3, 2023 10:00 AM UTC
+    const twoDaysAgoTimestamp = 1683108000;
+
+    expect(hasOneDayPassed(twoDaysAgoTimestamp)).toBe(true);
+  });
+
+  it('returns true for timestamps from a week ago', () => {
+    // 7 days ago - April 28, 2023 8:00 AM UTC
+    const weekAgoTimestamp = 1682668800;
+
+    expect(hasOneDayPassed(weekAgoTimestamp)).toBe(true);
+  });
+
+  it('returns true for null timestamp (defensive check)', () => {
+    expect(hasOneDayPassed(null)).toBe(true);
+  });
+
+  it('returns true for undefined timestamp (defensive check)', () => {
+    expect(hasOneDayPassed(undefined)).toBe(true);
+  });
+
+  it('returns true for zero timestamp (defensive check)', () => {
+    expect(hasOneDayPassed(0)).toBe(true);
+  });
+
+  it('returns true for empty string timestamp (defensive check)', () => {
+    expect(hasOneDayPassed('')).toBe(true);
+  });
+
+  it('handles cross-month boundaries correctly', () => {
+    // Set current time to May 1, 2023 12:00 PM UTC (1682942400)
+    const mayFirst = new Date(1682942400 * 1000);
+    vi.setSystemTime(mayFirst);
+
+    // April 29, 2023 12:00 PM UTC (1682769600) - 2 days ago, crossing month boundary
+    const crossMonthTimestamp = 1682769600;
+
+    expect(hasOneDayPassed(crossMonthTimestamp)).toBe(true);
+  });
+
+  it('handles cross-year boundaries correctly', () => {
+    // Set current time to January 2, 2023 12:00 PM UTC (1672660800)
+    const newYear = new Date(1672660800 * 1000);
+    vi.setSystemTime(newYear);
+
+    // December 30, 2022 12:00 PM UTC (1672401600) - 3 days ago, crossing year boundary
+    const crossYearTimestamp = 1672401600;
+
+    expect(hasOneDayPassed(crossYearTimestamp)).toBe(true);
+  });
+});
diff --git a/app/javascript/shared/helpers/timeHelper.js b/app/javascript/shared/helpers/timeHelper.js
index 6e041c7ec..5347d2410 100644
--- a/app/javascript/shared/helpers/timeHelper.js
+++ b/app/javascript/shared/helpers/timeHelper.js
@@ -3,6 +3,7 @@ import {
   isSameYear,
   fromUnixTime,
   formatDistanceToNow,
+  differenceInDays,
 } from 'date-fns';
 
 /**
@@ -91,3 +92,25 @@ export const shortTimestamp = (time, withAgo = false) => {
     .replace(' years ago', `y${suffix}`);
   return convertToShortTime;
 };
+
+/**
+ * Calculates the difference in days between now and a given timestamp.
+ * @param {Date} now - Current date/time.
+ * @param {number} timestampInSeconds - Unix timestamp in seconds.
+ * @returns {number} Number of days difference.
+ */
+export const getDayDifferenceFromNow = (now, timestampInSeconds) => {
+  const date = new Date(timestampInSeconds * 1000);
+  return differenceInDays(now, date);
+};
+
+/**
+ * Checks if more than 24 hours have passed since a given timestamp.
+ * Useful for determining if retry/refresh actions should be disabled.
+ * @param {number} timestamp - Unix timestamp.
+ * @returns {boolean} True if more than 24 hours have passed.
+ */
+export const hasOneDayPassed = timestamp => {
+  if (!timestamp) return true; // Defensive check
+  return getDayDifferenceFromNow(new Date(), timestamp) >= 1;
+};
diff --git a/app/javascript/shared/mixins/inboxMixin.js b/app/javascript/shared/mixins/inboxMixin.js
index bf8ec492b..c1f48f6f4 100644
--- a/app/javascript/shared/mixins/inboxMixin.js
+++ b/app/javascript/shared/mixins/inboxMixin.js
@@ -57,15 +57,15 @@ export default {
     isALineChannel() {
       return this.channelType === INBOX_TYPES.LINE;
     },
+    isAVoiceChannel() {
+      return this.channelType === INBOX_TYPES.VOICE;
+    },
     isAnEmailChannel() {
       return this.channelType === INBOX_TYPES.EMAIL;
     },
     isATelegramChannel() {
       return this.channelType === INBOX_TYPES.TELEGRAM;
     },
-    isAVoiceChannel() {
-      return this.channelType === INBOX_TYPES.VOICE;
-    },
     isATwilioSMSChannel() {
       const { medium: medium = '' } = this.inbox;
       return this.isATwilioChannel && medium === 'sms';
diff --git a/app/javascript/v3/App.vue b/app/javascript/v3/App.vue
index 992c0b381..ef7107beb 100644
--- a/app/javascript/v3/App.vue
+++ b/app/javascript/v3/App.vue
@@ -15,8 +15,10 @@ export default {
     setColorTheme() {
       if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
         this.theme = 'dark';
+        document.documentElement.classList.add('dark');
       } else {
-        this.theme = 'light ';
+        this.theme = 'light';
+        document.documentElement.classList.remove('dark');
       }
     },
     listenToThemeChanges() {
@@ -25,8 +27,10 @@ export default {
       mql.onchange = e => {
         if (e.matches) {
           this.theme = 'dark';
+          document.documentElement.classList.add('dark');
         } else {
           this.theme = 'light';
+          document.documentElement.classList.remove('dark');
         }
       };
     },
diff --git a/app/javascript/v3/api/auth.js b/app/javascript/v3/api/auth.js
index a4793d3d0..146db4e07 100644
--- a/app/javascript/v3/api/auth.js
+++ b/app/javascript/v3/api/auth.js
@@ -13,6 +13,16 @@ export const login = async ({
 }) => {
   try {
     const response = await wootAPI.post('auth/sign_in', credentials);
+
+    // Check if MFA is required
+    if (response.status === 206 && response.data.mfa_required) {
+      // Return MFA data instead of throwing error
+      return {
+        mfaRequired: true,
+        mfaToken: response.data.mfa_token,
+      };
+    }
+
     setAuthCredentials(response);
     clearLocalStorageOnLogout();
     window.location = getLoginRedirectURL({
@@ -20,8 +30,17 @@ export const login = async ({
       ssoConversationId,
       user: response.data.data,
     });
+    return null;
   } catch (error) {
+    // Check if it's an MFA required response
+    if (error.response?.status === 206 && error.response?.data?.mfa_required) {
+      return {
+        mfaRequired: true,
+        mfaToken: error.response.data.mfa_token,
+      };
+    }
     throwErrorMessage(error);
+    return null;
   }
 };
 
diff --git a/app/javascript/v3/views/auth/signup/Index.vue b/app/javascript/v3/views/auth/signup/Index.vue
index 508c755f5..86baff55c 100644
--- a/app/javascript/v3/views/auth/signup/Index.vue
+++ b/app/javascript/v3/views/auth/signup/Index.vue
@@ -62,7 +62,7 @@ export default {
           
           
           
-            
{{ $t('REGISTER.HAVE_AN_ACCOUNT') }}
+            
{{ $t('REGISTER.HAVE_AN_ACCOUNT') }} 
             
               {{ replaceInstallationName($t('LOGIN.TITLE')) }}
             
diff --git a/app/javascript/v3/views/login/Index.vue b/app/javascript/v3/views/login/Index.vue
index 4a51b3059..ff8022714 100644
--- a/app/javascript/v3/views/login/Index.vue
+++ b/app/javascript/v3/views/login/Index.vue
@@ -15,6 +15,7 @@ import FormInput from '../../components/Form/Input.vue';
 import GoogleOAuthButton from '../../components/GoogleOauth/Button.vue';
 import Spinner from 'shared/components/Spinner.vue';
 import NextButton from 'dashboard/components-next/button/Button.vue';
+import MfaVerification from 'dashboard/components/auth/MfaVerification.vue';
 
 const ERROR_MESSAGES = {
   'no-account-found': 'LOGIN.OAUTH.NO_ACCOUNT_FOUND',
@@ -29,6 +30,7 @@ export default {
     GoogleOAuthButton,
     Spinner,
     NextButton,
+    MfaVerification,
   },
   props: {
     ssoAuthToken: { type: String, default: '' },
@@ -58,6 +60,8 @@ export default {
         hasErrored: false,
       },
       error: '',
+      mfaRequired: false,
+      mfaToken: null,
     };
   },
   validations() {
@@ -87,8 +91,10 @@ export default {
       this.submitLogin();
     }
     if (this.authError) {
-      const message = ERROR_MESSAGES[this.authError] ?? 'LOGIN.API.UNAUTH';
-      useAlert(this.$t(message));
+      const messageKey = ERROR_MESSAGES[this.authError] ?? 'LOGIN.API.UNAUTH';
+      // Use a method to get the translated text to avoid dynamic key warning
+      const translatedMessage = this.getTranslatedMessage(messageKey);
+      useAlert(translatedMessage);
       // wait for idle state
       this.requestIdleCallbackPolyfill(() => {
         // Remove the error query param from the url
@@ -98,6 +104,18 @@ export default {
     }
   },
   methods: {
+    getTranslatedMessage(key) {
+      // Avoid dynamic key warning by handling each case explicitly
+      switch (key) {
+        case 'LOGIN.OAUTH.NO_ACCOUNT_FOUND':
+          return this.$t('LOGIN.OAUTH.NO_ACCOUNT_FOUND');
+        case 'LOGIN.OAUTH.BUSINESS_ACCOUNTS_ONLY':
+          return this.$t('LOGIN.OAUTH.BUSINESS_ACCOUNTS_ONLY');
+        case 'LOGIN.API.UNAUTH':
+        default:
+          return this.$t('LOGIN.API.UNAUTH');
+      }
+    },
     // TODO: Remove this when Safari gets wider support
     // Ref: https://caniuse.com/requestidlecallback
     //
@@ -140,7 +158,15 @@ export default {
       };
 
       login(credentials)
-        .then(() => {
+        .then(result => {
+          // Check if MFA is required
+          if (result?.mfaRequired) {
+            this.loginApi.showLoading = false;
+            this.mfaRequired = true;
+            this.mfaToken = result.mfaToken;
+            return;
+          }
+
           this.handleImpersonation();
           this.showAlertMessage(this.$t('LOGIN.API.SUCCESS_MESSAGE'));
         })
@@ -163,6 +189,17 @@ export default {
 
       this.submitLogin();
     },
+    handleMfaVerified() {
+      // MFA verification successful, continue with login
+      this.handleImpersonation();
+      window.location = '/app';
+    },
+    handleMfaCancel() {
+      // User cancelled MFA, reset state
+      this.mfaRequired = false;
+      this.mfaToken = null;
+      this.credentials.password = '';
+    },
   },
 };
 
@@ -193,7 +230,19 @@ export default {
         
       
     
+
+    
+    
+
+    
     
+    
+      
+        {{ headerText }}
+      
+
+      
+    
+
diff --git a/app/javascript/widget/components/Availability/AvailabilityText.story.vue b/app/javascript/widget/components/Availability/AvailabilityText.story.vue
new file mode 100644
index 000000000..aafcb3556
--- /dev/null
+++ b/app/javascript/widget/components/Availability/AvailabilityText.story.vue
@@ -0,0 +1,217 @@
+
+
+
+  
+    
+      
+    
+  
+
diff --git a/app/javascript/widget/components/Availability/AvailabilityText.vue b/app/javascript/widget/components/Availability/AvailabilityText.vue
new file mode 100644
index 000000000..649224d20
--- /dev/null
+++ b/app/javascript/widget/components/Availability/AvailabilityText.vue
@@ -0,0 +1,178 @@
+
+
+
+  
+    
+    
+      {{ replyTimeMessage }}
+    
+
+    
+    
+      {{
+        isOnline
+          ? replyTimeMessage
+          : t('TEAM_AVAILABILITY.BACK_AS_SOON_AS_POSSIBLE')
+      }}
+    
+
+    
+    
+    
+      {{ t('TEAM_AVAILABILITY.BACK_AS_SOON_AS_POSSIBLE') }}
+    
+
+    
+    
+      {{ t('REPLY_TIME.BACK_IN_SOME_TIME') }}
+    
+
+    
+    
+      {{ t('REPLY_TIME.BACK_TOMORROW') }}
+    
+
+    
+    
+      {{
+        t('REPLY_TIME.BACK_ON_DAY', {
+          day: dayNames[nextSlot.config.dayOfWeek],
+        })
+      }}
+    
+
+    
+    
+      {{
+        t('REPLY_TIME.BACK_IN_MINUTES', {
+          time: `${roundedMinutesUntilOpen}`,
+        })
+      }}
+    
+
+    
+    
+      {{ t('REPLY_TIME.BACK_IN_HOURS', adjustedHoursUntilOpen) }}
+    
+
+    
+    
+      {{
+        t('REPLY_TIME.BACK_AT_TIME', {
+          time: formattedOpeningTime,
+        })
+      }}
+    
+  
+
diff --git a/app/javascript/widget/components/ChatFooter.vue b/app/javascript/widget/components/ChatFooter.vue
index 841b37216..c85727a2b 100755
--- a/app/javascript/widget/components/ChatFooter.vue
+++ b/app/javascript/widget/components/ChatFooter.vue
@@ -6,7 +6,7 @@ import FooterReplyTo from 'widget/components/FooterReplyTo.vue';
 import ChatInputWrap from 'widget/components/ChatInputWrap.vue';
 import { BUS_EVENTS } from 'shared/constants/busEvents';
 import { sendEmailTranscript } from 'widget/api/conversation';
-import routerMixin from 'widget/mixins/routerMixin';
+import { useRouter } from 'vue-router';
 import { IFrameHelper } from '../helpers/utils';
 import { CHATWOOT_ON_START_CONVERSATION } from '../constants/sdkEvents';
 import { emitter } from 'shared/helpers/mitt';
@@ -17,7 +17,10 @@ export default {
     CustomButton,
     FooterReplyTo,
   },
-  mixins: [routerMixin],
+  setup() {
+    const router = useRouter();
+    return { router };
+  },
   data() {
     return {
       inReplyTo: null,
@@ -55,15 +58,8 @@ export default {
     emitter.on(BUS_EVENTS.TOGGLE_REPLY_TO_MESSAGE, this.toggleReplyTo);
   },
   methods: {
-    ...mapActions('conversation', [
-      'sendMessage',
-      'sendAttachment',
-      'clearConversations',
-    ]),
-    ...mapActions('conversationAttributes', [
-      'getAttributes',
-      'clearConversationAttributes',
-    ]),
+    ...mapActions('conversation', ['sendMessage', 'sendAttachment']),
+    ...mapActions('conversationAttributes', ['getAttributes']),
     async handleSendMessage(content) {
       await this.sendMessage({
         content,
@@ -84,9 +80,7 @@ export default {
       this.inReplyTo = null;
     },
     startNewConversation() {
-      this.clearConversations();
-      this.clearConversationAttributes();
-      this.replaceRoute('prechat-form');
+      this.router.replace({ name: 'prechat-form' });
       IFrameHelper.sendMessage({
         event: 'onEvent',
         eventIdentifier: CHATWOOT_ON_START_CONVERSATION,
diff --git a/app/javascript/widget/components/ChatHeader.vue b/app/javascript/widget/components/ChatHeader.vue
index 7c497b70f..578fb984e 100644
--- a/app/javascript/widget/components/ChatHeader.vue
+++ b/app/javascript/widget/components/ChatHeader.vue
@@ -1,55 +1,26 @@
-
 
@@ -79,9 +50,12 @@ export default {
               ${isOnline ? 'bg-n-teal-10' : 'hidden'}`"
           />