diff --git a/resources/js/Components/Common/Project/ProjectVisibilityFilterBadge.vue b/resources/js/Components/Common/Project/ProjectVisibilityFilterBadge.vue
new file mode 100644
index 00000000..c1e54f68
--- /dev/null
+++ b/resources/js/Components/Common/Project/ProjectVisibilityFilterBadge.vue
@@ -0,0 +1,46 @@
+
+
+
+
+
+ {{ option.name }}
+
+
+
diff --git a/resources/js/Components/Common/Project/ProjectsFilterDropdown.vue b/resources/js/Components/Common/Project/ProjectsFilterDropdown.vue
index 18a1ba73..24504678 100644
--- a/resources/js/Components/Common/Project/ProjectsFilterDropdown.vue
+++ b/resources/js/Components/Common/Project/ProjectsFilterDropdown.vue
@@ -1,6 +1,6 @@
@@ -102,6 +120,25 @@ const hasActiveFilters = computed(() => {
+
+
+
+
+ Visibility
+
+
+
+ {{ option.name }}
+
+
+
+
diff --git a/resources/js/Pages/Projects.vue b/resources/js/Pages/Projects.vue
index f096032b..113e7f11 100644
--- a/resources/js/Pages/Projects.vue
+++ b/resources/js/Pages/Projects.vue
@@ -20,6 +20,7 @@ import { isAllowedToPerformPremiumAction } from '@/utils/billing';
import { useStorage } from '@vueuse/core';
import ProjectsFilterDropdown from '@/Components/Common/Project/ProjectsFilterDropdown.vue';
import ProjectStatusFilterBadge from '@/Components/Common/Project/ProjectStatusFilterBadge.vue';
+import ProjectVisibilityFilterBadge from '@/Components/Common/Project/ProjectVisibilityFilterBadge.vue';
import ProjectClientFilterBadge from '@/Components/Common/Project/ProjectClientFilterBadge.vue';
import { NO_CLIENT_ID } from '@/Components/Common/Project/constants';
import type { SortColumn, SortDirection } from '@/Components/Common/Project/ProjectTable.vue';
@@ -36,6 +37,7 @@ interface ProjectTableState {
filters: {
clientIds: string[];
status: 'active' | 'archived' | 'all';
+ visibility: 'public' | 'private' | 'all';
};
}
@@ -47,6 +49,7 @@ const tableState = useStorage(
filters: {
clientIds: [],
status: 'all',
+ visibility: 'all',
},
},
undefined,
@@ -69,6 +72,14 @@ const filteredProjects = computed(() => {
return false;
}
+ // Visibility filter
+ if (tableState.value.filters.visibility === 'public' && !project.is_public) {
+ return false;
+ }
+ if (tableState.value.filters.visibility === 'private' && project.is_public) {
+ return false;
+ }
+
// Client filter
const hasClientFilter = tableState.value.filters.clientIds.length > 0;
if (hasClientFilter) {
@@ -91,6 +102,10 @@ function removeStatusFilter() {
tableState.value.filters.status = 'all';
}
+function removeVisibilityFilter() {
+ tableState.value.filters.visibility = 'all';
+}
+
function removeClientFilter() {
tableState.value.filters.clientIds = [];
}
@@ -152,6 +167,15 @@ const showBillableRate = computed(() => {
tableState.filters.status = $event as 'active' | 'archived' | 'all'
" />
+
+