Skip to content

Commit

Permalink
feat: Introduce schedule management and calendar components (#1327)
Browse files Browse the repository at this point in the history
* feat: Introduce schedule management and calendar components

- Add `WorksiteCalendar.vue` to manage worksite schedules with calendar, map, and upcoming view modes
- Implement schedule exporting in CSV, PDF, and ICS formats
- Integrate `@schedule-x` for calendar functionality
- Enable schedule editing and creation for worksite assignments
- Add detailed work type interfaces in `types`

fix: Improve existing components for better integration

- Modify `AjaxTable.vue` to emit `rowClick` and `selectionChanged` events
- Update `WorksiteTable.vue` styling and support passing custom table body styles
- Adjust incident handling in `AddFromList` and `List` components for more consistent query parameters

chore: Update dependencies for calendar integration

- Add `@schedule-x` dependencies to `package.json`

* refactor: remove Vuex ORM integration and simplify team data fetching

- Removed Vuex ORM and related dependencies in `AddScheduleDialog` test setup.
- Replaced Vuex ORM team fetching with direct `axios` call in `AddScheduleDialog.vue`.
- Cleaned up unused test code and adjusted mocking for consistency.

These changes simplify dependencies by removing Vuex ORM, streamlining the team data fetching process, and improving test maintainability.
  • Loading branch information
tabiodun authored Feb 12, 2025
1 parent 64eaca0 commit 56d1e60
Show file tree
Hide file tree
Showing 22 changed files with 2,252 additions and 101 deletions.
7 changes: 7 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,13 @@
"@pixi/settings": "6.5.10",
"@pixi/ticker": "6.5.10",
"@pixi/utils": "6.5.10",
"@schedule-x/calendar": "^2.18.0",
"@schedule-x/current-time": "^2.19.0",
"@schedule-x/drag-and-drop": "^2.18.0",
"@schedule-x/events-service": "^2.18.0",
"@schedule-x/resize": "^2.18.0",
"@schedule-x/theme-default": "^2.18.0",
"@schedule-x/vue": "^2.16.0",
"@sentry/integrations": "^7.111.0",
"@sentry/vue": "^8.27.0",
"@sipec/vue3-tags-input": "^3.0.4",
Expand Down
173 changes: 137 additions & 36 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/components/AjaxTable.vue
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ export default defineComponent({
default: '',
},
},
emits: ['rowClick', 'selectionChanged'],
setup(props) {
const { emitter } = useEmitter();
Expand Down
117 changes: 117 additions & 0 deletions src/components/WorksiteMapPopup.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,117 @@
<template>
<div class="flex flex-col">
<div class="flex items-center justify-between p-2">
<div></div>
<div class="flex gap-2 mr-2">
<ccu-icon
:alt="$t('casesVue.map_view')"
data-testid="testMapViewIcon"
size="medium"
class="cursor-pointer"
:class="showingMap ? 'filter-yellow' : 'filter-gray'"
type="map"
ccu-event="user_ui-view-map"
@click="() => showMap(true)"
/>
<ccu-icon
:alt="$t('casesVue.table_view')"
data-testid="testTableViewIcon"
size="medium"
class="cursor-pointer"
:class="showingTable ? 'filter-yellow' : 'filter-gray'"
type="table"
ccu-event="user_ui-view-table"
@click="showTable"
/>
</div>
</div>
<div class="relative flex-grow border-t">
<SimpleMap
v-show="showingMap"
:map-loading="false"
data-testid="mapPopupTest"
/>
<WorksiteTable
v-show="showingTable"
:worksite-query="props.query"
:body-style="{ height: '32rem' }"
@row-click="onSelectWorksite"
/>
</div>
</div>
</template>

<script setup lang="ts">
import SimpleMap from '@/components/SimpleMap.vue';
import useWorksiteMap from '@/hooks/worksite/useWorksiteMap';
import CcuIcon from '@/components/BaseIcon.vue';
import WorksiteTable from '@/components/work/WorksiteTable.vue';
import { loadCasesCached } from '@/utils/worksite';
import BaseCheckbox from '@/components/BaseCheckbox.vue';
const props = defineProps<{
incidentId: number;
query?: Record<string, any> | null;
}>();
const emits = defineEmits(['selectWorksite']);
let mapUtils: ReturnType<typeof useWorksiteMap> | null = null;
const showingMap = ref(true);
const showingTable = ref(false);
const showMap = (show: boolean) => {
showingMap.value = show;
showingTable.value = !show;
};
const showTable = () => {
showingTable.value = true;
showingMap.value = false;
};
const onSelectWorksite = (worksite: any) => {
emits('selectWorksite', worksite);
};
async function getWorksites() {
const response = await loadCasesCached(props.query);
return response.results;
}
/**
* Minimal example that fetches worksites for the given incident
* and sets a default or custom center.
*/
onMounted(async () => {
try {
// 1. Fetch worksites by incident
const worksites = await getWorksites(props.incidentId);
// 2. Initialize the map composable
mapUtils = useWorksiteMap(
worksites,
worksites.map((ws) => ws.id),
(w) => {
onSelectWorksite(w);
},
(_, map) => {
// Map centering logic
if (props.incidentCenter) {
// incidentCenter is typically [longitude, latitude]
map.setView([props.incidentCenter[1], props.incidentCenter[0]], 5);
} else {
// Fallback center if none is provided
map.setView([35.7465, -96.4115], 5);
}
},
);
} catch (error) {
console.error('Error fetching worksites for popup map:', error);
}
});
</script>

<style scoped>
/* You can style your popup container here if needed */
</style>
25 changes: 17 additions & 8 deletions src/components/locations/LocationViewer.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ export default defineComponent({
useGoogleMaps: {
type: Boolean,
},
allowReposition: {
type: Boolean,
default: true,
},
customSvgIcon: {
type: String,
},
},
emits: ['updatedLocation'],
setup(props, { emit }) {
Expand All @@ -40,7 +47,7 @@ export default defineComponent({
function addMarkerToMap() {
const svgIcon = L.divIcon({
className: 'crisiscleanup-map-marker',
html: templates.map_marker,
html: props.customSvgIcon || templates.map_marker,
iconAnchor: [20, 40],
iconSize: [50, 50],
});
Expand All @@ -50,7 +57,7 @@ export default defineComponent({
markerLayer.value.clearLayers();
const marker = new (L.marker as any)(
[markerLocation.coordinates[1], markerLocation.coordinates[0]],
{ draggable: 'true', icon: svgIcon },
{ draggable: props.allowReposition, icon: svgIcon },
);
marker.addTo(markerLayer.value);
marker.on('dragend', (event: LeafletEvent) => {
Expand All @@ -60,12 +67,14 @@ export default defineComponent({
[markerLocation.coordinates[1], markerLocation.coordinates[0]],
15,
);
marker
.bindTooltip(t('casesVue.drag_pin_to_correct_location'), {
direction: 'top',
offset: L.point({ x: 0, y: -40 }),
})
.openTooltip();
if (props.allowReposition) {
marker
.bindTooltip(t('casesVue.drag_pin_to_correct_location'), {
direction: 'top',
offset: L.point({ x: 0, y: -40 }),
})
.openTooltip();
}
}
onMounted(() => {
Expand Down
Loading

0 comments on commit 56d1e60

Please sign in to comment.