Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 130 additions & 59 deletions web/src/components/case-details/civil/CivilDocumentsView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,11 @@
<v-row>
<v-col cols="6" />
<v-col cols="3" class="ml-auto" v-if="documentCategories.length > 1">
<v-select
v-model="selectedCategory"
placeholder="All documents"
hide-details
<ChipMultiSelect
v-model="selectedCategories"
:items="documentCategories"
item-title="title"
item-value="value"
>
<template v-slot:item="{ props: itemProps, item }">
<v-list-item
v-bind="itemProps"
:title="`${item.title} (${categoryCount(item.raw.value)})`"
></v-list-item>
</template>
</v-select>
:select-all-count="uniqueDocuments.length"
/>
</v-col>
</v-row>
<AllDocuments
Expand All @@ -43,9 +33,10 @@
:openIndividualDocument
:selectedItems
:binderDocumentIds="currentBinder?.documents.map((d) => d.documentId) ?? []"
:selectedCategory="selectedCategory"
:hasActiveFilters="activeCategories.length > 0"
:isScheduledView="isScheduledOnlySelected"
:sectionTitle="allDocumentsSectionTitle"
:sortBy
:getCategoryDisplayTitle="getCategoryDisplayTitle"
@update:selectedItems="(val) => (selectedItems = val)"
/>

Expand Down Expand Up @@ -121,12 +112,22 @@
DocumentRequestType,
} from '@/types/shared';
import { getCourtClassStyle, getRoles } from '@/utils/utils';
import {
DEFAULT_OTHER_LABEL,
getActiveSelections,
pruneInvalidSelections,
getSectionTitle,
getUncategorizedCount,
isAllOptionsSelected,
matchesCategorySelection,
} from '@/utils/categoryFilterUtils';
import {
mdiFileDocumentMultipleOutline,
mdiNotebookOutline,
mdiNotebookRemoveOutline,
} from '@mdi/js';
import { computed, inject, onMounted, ref } from 'vue';
import { computed, inject, onMounted, ref, watch } from 'vue';
import ChipMultiSelect from '../common/ChipMultiSelect.vue';
import AllDocuments from './documents/AllDocuments.vue';
import JudicialBinder from './documents/JudicialBinder.vue';

Expand All @@ -148,6 +149,7 @@
const CSR_CATEGORY_DESC = 'Court Summary';
const AFF_FIN_STMT = 'Affidavits/Financial Stmts';
const LITIGANT = 'Litigant';
const OTHER_CATEGORY = DEFAULT_OTHER_LABEL;

const selectedItems = ref<civilDocumentType[]>([]);
const selectedBinderItems = ref<civilDocumentType[]>([]);
Expand All @@ -171,14 +173,36 @@
const scheduledDocuments = computed(() =>
uniqueDocuments.value.filter((doc) => doc.nextAppearanceDt)
);
const selectedCategory = ref<string | undefined>(
scheduledDocuments.value.length > 0 ? SCHEDULED_CATEGORY : undefined
const selectedCategories = ref<string[]>(
scheduledDocuments.value.length > 0 ? [SCHEDULED_CATEGORY] : []
);
const isBinderLoading = ref(true);
const rolesLoading = ref(false);
const roles = ref<LookupCode[]>();
const currentBinder = ref<Binder>();
const courtClassCdStyle = getCourtClassStyle(props.courtClassCd);
const selectedCategory = computed<string | undefined>(() => {
return selectedCategories.value.length === 1
? selectedCategories.value[0]
: undefined;
});
const isAllSelected = computed<boolean>(() =>
isAllOptionsSelected(
selectedCategories.value,
documentCategories.value.length
)
);
const activeCategories = computed<string[]>(() =>
getActiveSelections(selectedCategories.value, isAllSelected.value)
);
const isScheduledOnlySelected = computed<boolean>(
() =>
activeCategories.value.length === 1 &&
activeCategories.value[0] === SCHEDULED_CATEGORY
);
const allDocumentsSectionTitle = computed<string>(() =>
getSectionTitle(activeCategories.value, getCategoryDisplayTitle)
);
const sortBy = computed<[{ key: string; order: 'desc' | 'asc' }]>(() => {
return selectedCategory?.value === CSR_CATEGORY
? [{ key: 'filedDt', order: 'desc' as const }]
Expand All @@ -187,7 +211,7 @@

const headers = computed<DataTableHeader[]>(() => {
const baseHeaders = shared.getBaseCivilDocumentTableHeaders(
selectedCategory.value === SCHEDULED_CATEGORY
isScheduledOnlySelected.value
);

return [
Expand Down Expand Up @@ -216,39 +240,102 @@
return categoryMap[category] || category;
};

const documentCategories = computed<{ title: string; value: string }[]>(() =>
(scheduledDocuments.value.length > 0
? [{ title: SCHEDULED_CATEGORY, value: SCHEDULED_CATEGORY }]
: []
const getUncategorizedDocumentCount = (): number =>
getUncategorizedCount(uniqueDocuments.value, (doc) => doc.category);

const categoryCount = (category: string): number => {
if (category.toLowerCase() === SCHEDULED_CATEGORY.toLowerCase()) {
return uniqueDocuments.value.filter((doc) => doc.nextAppearanceDt).length;
}

if (
category.toLowerCase() === CSR_CATEGORY_DESC.toLowerCase() ||
category.toLowerCase() === CSR_CATEGORY.toLowerCase()
) {
return uniqueDocuments.value.filter(
(doc) =>
doc.category?.trim().toLowerCase() === CSR_CATEGORY.toLowerCase()
).length;
}

if (category.toLowerCase() === OTHER_CATEGORY.toLowerCase()) {
return getUncategorizedDocumentCount();
}

return uniqueDocuments.value.filter(
(doc) => doc.category?.trim().toLowerCase() === category.toLowerCase()
).length;
};

const documentCategories = computed<
{ title: string; value: string; count: number }[]
>(() => {
const uncategorizedDocumentCount = getUncategorizedDocumentCount();

return (
scheduledDocuments.value.length > 0
? [
{
title: SCHEDULED_CATEGORY,
value: SCHEDULED_CATEGORY,
count: categoryCount(SCHEDULED_CATEGORY),
},
]
: []
).concat(
[
...new Set(
uniqueDocuments.value
.filter((d) => d.category)
.map((doc) => doc.category)
),
].map((category) => ({
title: getCategoryDisplayTitle(category),
value: category,
}))
)
);

const filterByCategory = (item: civilDocumentType) => {
const category = selectedCategory.value?.toLowerCase();
if (!category) {
return true;
}
]
.map((category) => ({
title: getCategoryDisplayTitle(category),
value: category,
count: categoryCount(category),
}))
.concat(
uncategorizedDocumentCount > 0
? [
{
title: OTHER_CATEGORY,
value: OTHER_CATEGORY,
count: uncategorizedDocumentCount,
},
]
: []
)
);
});

if (category === SCHEDULED_CATEGORY.toLowerCase()) {
return !!item.nextAppearanceDt;
}
watch(
documentCategories,
(categories) => {
const filteredSelections = pruneInvalidSelections(
selectedCategories.value,
categories.map((category) => category.value)
);

if (category === CSR_CATEGORY_DESC.toLowerCase()) {
return item.category === CSR_CATEGORY;
}
if (filteredSelections.length !== selectedCategories.value.length) {
selectedCategories.value = filteredSelections;
}
},
{ immediate: true }
);

return item.category?.toLowerCase() === category;
const filterByCategory = (item: civilDocumentType) => {
return matchesCategorySelection(
item,
activeCategories.value,
(doc) => doc.category,
{
otherLabel: OTHER_CATEGORY,
specialPredicates: {
[SCHEDULED_CATEGORY.toLowerCase()]: (doc) => !!doc.nextAppearanceDt,
},
}
);
};

const filteredDocuments = computed(() =>
Expand All @@ -273,22 +360,6 @@
.filter((item): item is civilDocumentType => item !== undefined);
});

const categoryCount = (category: string): number => {
if (category.toLowerCase() === SCHEDULED_CATEGORY.toLowerCase()) {
return uniqueDocuments.value.filter((doc) => doc.nextAppearanceDt).length;
}

if (category.toLowerCase() === CSR_CATEGORY_DESC.toLowerCase()) {
return uniqueDocuments.value.filter(
(doc) => doc.category === CSR_CATEGORY
).length;
}

return uniqueDocuments.value.filter(
(doc) => doc.category?.toLowerCase() === category.toLowerCase()
).length;
};

onMounted(async () => {
try {
rolesLoading.value = true;
Expand Down
18 changes: 6 additions & 12 deletions web/src/components/case-details/civil/documents/AllDocuments.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,12 @@
color="var(--bg-gray-500)"
elevation="0"
data-testid="all-documents-container"
v-if="documents?.length > 0"
v-if="documents?.length > 0 || props.hasActiveFilters"
>
<v-card-text>
<v-row align="center" no-gutters>
<v-col class="text-h5" cols="6">
{{
props.selectedCategory && props.getCategoryDisplayTitle
? props.getCategoryDisplayTitle(props.selectedCategory)
: 'All Documents'
}}
{{ props.sectionTitle || 'All Documents' }}
({{ documents.length }})
</v-col>
</v-row>
Expand Down Expand Up @@ -53,10 +49,7 @@
<span v-else>
{{ item.documentTypeDescription }}
</span>
<span
v-if="selectedCategory === 'Scheduled' && item.filedDt"
class="text-caption"
>
<span v-if="isScheduledView && item.filedDt" class="text-caption">
<br />
Date Filed: {{ formatDateToDDMMMYYYY(item.filedDt) }}
</span>
Expand Down Expand Up @@ -104,9 +97,10 @@
baseHeaders: DataTableHeader[];
binderDocumentIds: string[];
addDocumentToBinder: (document: civilDocumentType) => void;
selectedCategory?: string;
hasActiveFilters?: boolean;
isScheduledView?: boolean;
sectionTitle?: string;
sortBy?: [{ key: string; order: 'asc' | 'desc' }];
getCategoryDisplayTitle?: (category: string) => string;
openIndividualDocument: (data: civilDocumentType) => void;
}>();
const emit =
Expand Down
Loading
Loading