Skip to content

Commit 577a4da

Browse files
authored
Merge pull request #21 from codebar-ag/main
m/p
2 parents a8992c0 + 7aac29f commit 577a4da

23 files changed

+476
-188
lines changed

changelog_internal.md

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,296 @@ Removed redundant status column from members table to maintain consistency with
244244
245245
**Result:** Members table now shows: Name → Email → Role → Billable Rate → Edit
246246
247+
### Remove Pie Chart from Reporting Pages
248+
249+
Completely removed the ReportingPieChart component from the entire application.
250+
251+
**Files modified:**
252+
- `resources/js/Components/Common/Reporting/ReportingOverview.vue`
253+
- `resources/js/Pages/SharedReport.vue`
254+
255+
**Component removed:** `ReportingPieChart` (equivalent to the `ProjectsChartCard` removed from dashboard)
256+
257+
**Removed imports:**
258+
```js
259+
- import ReportingPieChart from '@/Components/Common/Reporting/ReportingPieChart.vue';
260+
```
261+
262+
**Removed from templates:**
263+
```vue
264+
- <div class="px-2 lg:px-4">
265+
- <ReportingPieChart
266+
- :data="groupedPieChartData"></ReportingPieChart>
267+
- </div>
268+
```
269+
270+
**Removed computed properties:**
271+
```js
272+
- const groupedPieChartData = computed(() => { ... });
273+
```
274+
275+
**File to delete:** `resources/js/Components/Common/Reporting/ReportingPieChart.vue` (component file no longer needed)
276+
277+
**Layout changes:**
278+
- Removed sidebar layout (grid-cols-4)
279+
- Table now spans full width
280+
- Bar chart (ReportingChart) remains for data visualization
281+
282+
**Result:** ReportingPieChart component completely removed from the application - no imports, no usage, no data generation.
283+
284+
### Performance Optimization: Projects Search Filter
285+
286+
Optimized the search filter in Projects.vue to improve performance when searching through projects and their associated clients.
287+
288+
**File modified:** `resources/js/Pages/Projects.vue`
289+
290+
**Problem:** O(n*m) complexity - the client lookup inside the filter loop was inefficient
291+
- For each project (n), was calling `clients.value.find()` (m operations)
292+
- With many projects and clients, this created performance bottlenecks
293+
294+
**Solution:** Create clientsMap before filtering for O(1) lookup
295+
296+
**Before:**
297+
```js
298+
// Search in client name
299+
const client = clients.value.find(client => client.id === project.client_id);
300+
const clientNameMatch = client?.name.toLowerCase().includes(query) || false;
301+
```
302+
303+
**After:**
304+
```js
305+
// Create clients map for O(1) lookup performance
306+
const clientsMap = new Map(clients.value.map(c => [c.id, c]));
307+
308+
filteredProjects = filteredProjects.filter((project) => {
309+
// Search in client name
310+
const client = clientsMap.get(project.client_id);
311+
const clientNameMatch = client?.name.toLowerCase().includes(query) || false;
312+
// ...
313+
});
314+
```
315+
316+
**Performance improvement:** O(n*m) → O(n+m) complexity
317+
- Map creation: O(m) - done once
318+
- Lookups: O(1) per project instead of O(m)
319+
- Significant improvement with large datasets
320+
321+
### CSS Cleanup: Remove Redundant Tailwind Classes
322+
323+
Fixed duplicate and redundant CSS class declarations across all table components throughout the application.
324+
325+
**Problem:** Many table components had duplicate `3xl:pl-12` classes in their Tailwind CSS declarations
326+
- Some had simple duplicates: `pl-4 sm:pl-6 lg:pl-8 3xl:pl-12` (redundant `3xl:pl-12`)
327+
- Some had double duplicates: `3xl:pl-12 ... pl-4 sm:pl-6 lg:pl-8 3xl:pl-12` (appearing twice!)
328+
329+
**Files cleaned up:**
330+
- `resources/js/Components/Common/Client/ClientTableRow.vue`
331+
- `resources/js/Components/Common/Client/ClientTableHeading.vue`
332+
- `resources/js/Components/Common/Tag/TagTableHeading.vue`
333+
- `resources/js/Components/Common/Tag/TagTableRow.vue`
334+
- `resources/js/Components/Common/ProjectMember/ProjectMemberTableHeading.vue`
335+
- `resources/js/Components/Common/ProjectMember/ProjectMemberTableRow.vue`
336+
- `resources/js/Components/Common/Invitation/InvitationTableRow.vue`
337+
- `resources/js/Components/Common/Invitation/InvitationTableHeading.vue`
338+
- `resources/js/Components/Common/Report/ReportTableHeading.vue`
339+
- `resources/js/Components/Common/Report/ReportTableRow.vue`
340+
- `resources/js/Components/Common/Member/MemberTableRow.vue`
341+
- `resources/js/Components/Common/Member/MemberTableHeading.vue`
342+
- `resources/js/Components/Common/Project/ProjectTableRow.vue`
343+
- `resources/js/Components/Common/Project/ProjectTableHeading.vue`
344+
- `resources/js/Components/Common/Task/TaskTableHeading.vue`
345+
- `resources/js/Components/Common/Task/TaskTableRow.vue`
346+
347+
**Changes made:**
348+
```css
349+
/* Before - redundant classes */
350+
class="... pl-4 sm:pl-6 lg:pl-8 3xl:pl-12"
351+
class="... 3xl:pl-12 ... pl-4 sm:pl-6 lg:pl-8 3xl:pl-12"
352+
353+
/* After - clean responsive padding */
354+
class="... pl-4 sm:pl-6 lg:pl-8"
355+
```
356+
357+
**Benefits:**
358+
- Cleaner, more maintainable CSS
359+
- Eliminates potential conflicts from duplicate declarations
360+
- Consistent responsive padding across all table components
361+
- Smaller CSS bundle size
362+
363+
### Fix Client Table Column Positioning
364+
365+
Fixed layout issue where Projects column had excessive spacing from Name column.
366+
367+
**File:** `resources/js/Components/Common/Client/ClientTableRow.vue`
368+
369+
**Problem:** Projects column had excessive padding pushing it away from Name column.
370+
371+
**Fixed styling:**
372+
```vue
373+
- class="whitespace-nowrap flex items-center space-x-5 3xl:pl-12 py-4 pr-3 text-sm font-medium text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12"
374+
+ class="whitespace-nowrap py-4 pr-3 text-sm font-medium text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12"
375+
376+
- class="whitespace-nowrap flex items-center space-x-5 3xl:pl-12 py-4 pr-3 text-sm font-medium text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12"
377+
+ class="whitespace-nowrap px-3 py-4 text-sm text-text-secondary"
378+
```
379+
380+
**Result:** Projects column now appears directly next to Name column with proper spacing.
381+
382+
### Restore Weekly Project Overview API Query
383+
384+
Fixed issue where removing ProjectsChartCard accidentally broke other dashboard functionality.
385+
386+
**File:** `resources/js/Components/Dashboard/ThisWeekOverview.vue`
387+
388+
**Problem:** When removing the ProjectsChartCard component, the `weeklyProjectOverview` API query was also removed, which might be used by other parts of the dashboard.
389+
390+
**Fixed by restoring API query:**
391+
```js
392+
// Set up the queries
393+
const { data: weeklyProjectOverview } = useQuery({
394+
queryKey: ['weeklyProjectOverview', organizationId],
395+
queryFn: () => {
396+
return api.weeklyProjectOverview({
397+
params: {
398+
organization: organizationId.value!,
399+
},
400+
});
401+
},
402+
enabled: computed(() => !!organizationId.value),
403+
});
404+
```
405+
406+
**Result:** Dashboard data should now load properly without the ProjectsChartCard component being displayed.
407+
408+
### Add Search/Filter Functionality to Projects and Clients Pages
409+
410+
Added real-time search functionality with wildcard matching to improve user experience.
411+
412+
#### Projects Page Search
413+
414+
**File:** `resources/js/Pages/Projects.vue`
415+
416+
**Added imports:**
417+
```js
418+
import { MagnifyingGlassIcon } from '@heroicons/vue/20/solid';
419+
```
420+
421+
**Added search state:**
422+
```js
423+
const searchQuery = ref('');
424+
```
425+
426+
**Updated filtering logic:**
427+
```js
428+
const shownProjects = computed(() => {
429+
let filteredProjects = projects.value.filter((project) => {
430+
if (activeTab.value === 'active') {
431+
return !project.is_archived;
432+
}
433+
return project.is_archived;
434+
});
435+
436+
// Apply search filter
437+
if (searchQuery.value.trim()) {
438+
const query = searchQuery.value.toLowerCase().trim();
439+
filteredProjects = filteredProjects.filter((project) => {
440+
// Search in project name
441+
const projectNameMatch = project.name.toLowerCase().includes(query);
442+
443+
// Search in client name
444+
const client = clients.value.find(client => client.id === project.client_id);
445+
const clientNameMatch = client?.name.toLowerCase().includes(query) || false;
446+
447+
return projectNameMatch || clientNameMatch;
448+
});
449+
}
450+
451+
return filteredProjects;
452+
});
453+
```
454+
455+
**Added search input UI:**
456+
```vue
457+
<div class="flex items-center space-x-3">
458+
<div class="relative">
459+
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
460+
<MagnifyingGlassIcon class="h-5 w-5 text-text-secondary" />
461+
</div>
462+
<input
463+
v-model="searchQuery"
464+
type="text"
465+
placeholder="Search projects or clients..."
466+
class="block w-64 pl-10 pr-3 py-2 border border-input-border rounded-md leading-5 bg-input-background text-text-primary placeholder-text-secondary focus:outline-none focus:ring-1 focus:ring-accent-500 focus:border-accent-500 sm:text-sm"
467+
/>
468+
</div>
469+
<SecondaryButton>Create Project</SecondaryButton>
470+
</div>
471+
```
472+
473+
#### Clients Page Search
474+
475+
**File:** `resources/js/Pages/Clients.vue`
476+
477+
**Added imports:**
478+
```js
479+
import { MagnifyingGlassIcon } from '@heroicons/vue/20/solid';
480+
```
481+
482+
**Added search state:**
483+
```js
484+
const searchQuery = ref('');
485+
```
486+
487+
**Updated filtering logic:**
488+
```js
489+
const shownClients = computed(() => {
490+
let filteredClients = clients.value.filter((client) => {
491+
if (activeTab.value === 'active') {
492+
return !client.is_archived;
493+
}
494+
return client.is_archived;
495+
});
496+
497+
// Apply search filter
498+
if (searchQuery.value.trim()) {
499+
const query = searchQuery.value.toLowerCase().trim();
500+
filteredClients = filteredClients.filter((client) => {
501+
return client.name.toLowerCase().includes(query);
502+
});
503+
}
504+
505+
return filteredClients;
506+
});
507+
```
508+
509+
**Added search input UI:**
510+
```vue
511+
<div class="flex items-center space-x-3">
512+
<div class="relative">
513+
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
514+
<MagnifyingGlassIcon class="h-5 w-5 text-text-secondary" />
515+
</div>
516+
<input
517+
v-model="searchQuery"
518+
type="text"
519+
placeholder="Search clients..."
520+
class="block w-64 pl-10 pr-3 py-2 border border-input-border rounded-md leading-5 bg-input-background text-text-primary placeholder-text-secondary focus:outline-none focus:ring-1 focus:ring-accent-500 focus:border-accent-500 sm:text-sm"
521+
/>
522+
</div>
523+
<SecondaryButton>Create Client</SecondaryButton>
524+
</div>
525+
```
526+
527+
#### Features
528+
529+
- **Real-time filtering:** Results update as you type
530+
- **Wildcard search:** Substring/partial matching
531+
- **Projects page:** Searches both project names AND client names
532+
- **Clients page:** Searches client names
533+
- **Case-insensitive:** Search works regardless of capitalization
534+
- **Works with tabs:** Search applies to both Active and Archived tabs
535+
- **Clean UI:** Search input with magnifying glass icon, positioned next to action buttons
536+
247537
### Remove Pull Request Template
248538
249539
**File:** `.github/PULL_REQUEST_TEMPLATE.md`

composer.lock

Lines changed: 6 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

resources/js/Components/Common/Client/ClientTableHeading.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import TableHeading from '@/Components/Common/TableHeading.vue';
44

55
<template>
66
<TableHeading>
7-
<div class="py-1.5 pr-3 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">Name</div>
7+
<div class="py-1.5 pr-3 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8">Name</div>
88
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">Projects</div>
99
<div class="relative py-1.5 pl-3 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12">
1010
<span class="sr-only">Edit</span>

resources/js/Components/Common/Client/ClientTableRow.vue

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,14 @@ const showEditModal = ref(false);
4040
<ClientEditModal
4141
v-model:show="showEditModal"
4242
:client="client"></ClientEditModal>
43-
<div
44-
class="whitespace-nowrap flex items-center space-x-5 3xl:pl-12 py-4 pr-3 text-sm font-medium text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
43+
<div class="whitespace-nowrap py-4 pr-3 text-sm font-medium text-text-primary pl-4 sm:pl-6 lg:pl-8">
4544
<span>
4645
{{ client.name }}
4746
</span>
4847
</div>
4948
<div
50-
class="whitespace-nowrap flex items-center space-x-5 3xl:pl-12 py-4 pr-3 text-sm font-medium text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
51-
<span class="text-text-secondary"> {{ projectCount }} Projects </span>
49+
class="whitespace-nowrap px-3 py-4 text-sm text-text-secondary">
50+
<span> {{ projectCount }} Projects </span>
5251
</div>
5352
<div
5453
class="relative whitespace-nowrap flex items-center pl-3 text-right text-sm font-medium sm:pr-0 pr-4 sm:pr-6 lg:pr-8 3xl:pr-12">

resources/js/Components/Common/Invitation/InvitationTableHeading.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import TableHeading from '@/Components/Common/TableHeading.vue';
55
<template>
66
<TableHeading>
77
<div
8-
class="px-3 py-1.5 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
8+
class="px-3 py-1.5 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8">
99
Email
1010
</div>
1111
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">Role</div>

resources/js/Components/Common/Invitation/InvitationTableRow.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ async function resendInvitation() {
5757
<template>
5858
<TableRow>
5959
<div
60-
class="whitespace-nowrap px-3 py-4 text-sm text-text-secondary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
60+
class="whitespace-nowrap px-3 py-4 text-sm text-text-secondary pl-4 sm:pl-6 lg:pl-8">
6161
{{ invitation.email }}
6262
</div>
6363
<div class="whitespace-nowrap px-3 py-4 text-sm text-text-secondary">

resources/js/Components/Common/Member/MemberTableHeading.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import TableHeading from '@/Components/Common/TableHeading.vue';
55
<template>
66
<TableHeading>
77
<div
8-
class="py-1.5 pr-3 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
8+
class="py-1.5 pr-3 text-left font-semibold text-text-primary pl-4 sm:pl-6 lg:pl-8">
99
Name
1010
</div>
1111
<div class="px-3 py-1.5 text-left font-semibold text-text-primary">Email</div>

resources/js/Components/Common/Member/MemberTableRow.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ const userHasValidMailAddress = computed(() => {
6060
<template>
6161
<TableRow>
6262
<div
63-
class="whitespace-nowrap flex items-center space-x-5 py-4 pr-3 text-sm font-medium text-text-primary pl-4 sm:pl-6 lg:pl-8 3xl:pl-12">
63+
class="whitespace-nowrap flex items-center space-x-5 py-4 pr-3 text-sm font-medium text-text-primary pl-4 sm:pl-6 lg:pl-8">
6464
<span>
6565
{{ member.name }}
6666
</span>

0 commit comments

Comments
 (0)