Skip to content

Add location slug routing and enhance dashboard navigation #70

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 5, 2025
Merged

Conversation

timDeHof
Copy link
Owner

@timDeHof timDeHof commented Aug 5, 2025

Pull Request Description
Changes
This PR adds location slug support and enhances navigation throughout the travel log application.

Commit Summary
1a38815 Add location slug support and enhance navigation

Implements location slug-based routing with new API endpoint /api/locations/[slug].get.ts

Adds findLocation database query function to retrieve locations by slug and user ID

Enhances map component with point selection logic and navigation links in popups

Updates sidebar button component to support both href and RouteLocationRaw navigation

Adds database relations between location and locationLog tables

Implements utility functions for map point creation and selection comparison

Adds vue-tsc dependency and typecheck script for better TypeScript support

Updates location cards to be clickable links navigating to individual location pages

0a6dcf7 feat(ui): add location log support and enhance dashboard navigation

Creates new location detail page with slug-based routing at /dashboard/location/[slug]

Adds placeholder pages for location editing and location log creation

Implements dynamic sidebar navigation that changes based on current route context

Enhances locations store with separate state management for current location vs all locations

Adds TypeScript types for SelectLocationLog and SelectLocationWithLogs

Updates dashboard layout to show contextual navigation items based on current page

closes #32

Summary by CodeRabbit

  • New Features

    • Added navigation links to map popups for easier access to location details.
    • Introduced dedicated pages for viewing, adding, and editing individual locations.
    • Sidebar now dynamically updates its items based on the current route and selected location.
    • Location cards in the dashboard are now clickable, enabling direct navigation to location details.
  • Improvements

    • Enhanced map interaction with smoother animations and improved selection highlighting.
    • Sidebar and map points update contextually based on user navigation.
    • Improved loading and error handling for location data.
  • Developer Experience

    • Added a type checking script for improved code quality.
    • Refactored internal logic for better maintainability and consistency.

- Added slug field to location schema for URL-friendly identifiers
- Updated map and sidebar components with improved navigation handling
- Enhanced location queries and stores for better data management
- Added clickable points on map with proper routing
- Improved type safety and dependency versions
- Added new navigation items for location logs and editing
- Created new Vue components for location log management
- Enhanced sidebar structure with dynamic top navigation
- Improved location data handling in stores
- Added support for viewing location logs in the dashboard

This commit introduces new features for managing location data and improves the overall navigation structure in the dashboard UI.
Copy link

vercel bot commented Aug 5, 2025

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
nuxt-travel-log ✅ Ready (Inspect) Visit Preview 💬 Add feedback Aug 5, 2025 4:23am

Copy link

coderabbitai bot commented Aug 5, 2025

Walkthrough

This update introduces dynamic, route-aware sidebar navigation for location-specific pages, including new sidebar item types and logic. It adds database relations and queries for locations and logs, new utility functions for map point handling, and several new or refactored Vue components and store logic. Navigation and selection logic are standardized throughout.

Changes

Cohort / File(s) Change Summary
Sidebar Navigation & Logic
pages/dashboard.vue, pages/dashboard/index.vue, pages/dashboard/location/[slug].vue, pages/dashboard/location/[slug]/edit.vue, pages/dashboard/location/[slug]/add.vue, components/sidebar-button.vue, stores/sidebar.ts
Sidebar items are now dynamically generated based on the current route, supporting both href and to navigation. New location-specific sidebar links are shown on detail pages, and sidebar item types and props are updated for flexibility.
Location Data & Relations
lib/db/queries/location.ts, lib/db/schema/location.ts, lib/db/schema/location-log.ts, lib/types.ts, stores/locations.ts, server/api/locations/[slug].get.ts
Database schema updated to define explicit relations between locations and logs. New query and API endpoint for fetching a location by slug and user. Store logic expanded to manage both location lists and individual locations, with typed support for related logs.
Map Point Utilities & Logic
utils/map-points.ts, components/app/map.client.vue, stores/map.ts
Introduces utility functions for converting locations to map points and for selection checks. Map component and store updated to use these helpers, standardizing selection logic and improving popup navigation. Map animation and bounds behavior adjusted.
Type and Dependency Updates
package.json
Adds a type-checking script and a new dev dependency for TypeScript support.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant Sidebar
    participant LocationsStore
    participant Router

    User->>Router: Navigates to /dashboard/location/:slug
    Router->>LocationsStore: Triggers fetch for current location by slug
    LocationsStore->>Sidebar: Updates SidebarTopItems (links: Locations, This Location, Edit Location)
    Sidebar->>User: Renders updated sidebar with location-specific links
Loading
sequenceDiagram
    participant User
    participant MapComponent
    participant Utils

    User->>MapComponent: Hovers/clicks a map point
    MapComponent->>Utils: Calls isPointSelected(point, selectedPoint)
    Utils-->>MapComponent: Returns selection status
    MapComponent->>User: Updates tooltip/icon/selection state
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~40 minutes

Assessment against linked issues

Objective Addressed Explanation
Sidebar displays link back to "Locations" page, Sidebar displays link to this specific location, Sidebar displays link to edit this specific location ([#32])
Location list in sidebar is no longer displayed on location detail page ([#32])

Assessment against linked issues: Out-of-scope changes

Code Change Explanation
Adjustment of map animation parameters and fitBounds options (stores/map.ts lines related to flyTo and fitBounds) These changes pertain to map animation and zoom behavior, which are unrelated to sidebar navigation or location-specific links.
Addition of type-checking script and dev dependency (package.json) Adding a type-checking script and dependency is not required for sidebar navigation changes.

Possibly related PRs

  • timDeHof/nuxt-travel-log#66: Both PRs enhance map marker interaction and popup content, including dynamic styling and navigation, indicating a direct code-level connection.
  • timDeHof/nuxt-travel-log#59: This PR builds upon the initial creation of the sidebar-button.vue component, extending its navigation prop handling.
  • timDeHof/nuxt-travel-log#62: Both PRs modify and extend location query logic in lib/db/queries/location.ts, adding related database functionality.

Poem

A bunny hopped through sidebar lanes,
With links that change as routes rearrange.
Locations now have pride of place,
Edit and view with elegant grace.
The map and logs in harmony sing—
Oh, what delight these updates bring!
🐇✨

Note

⚡️ Unit Test Generation is now available in beta!

Learn more here, or try it out under "Finishing Touches" below.

✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch ntl-32

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai generate unit tests to generate unit tests for this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 8

🧹 Nitpick comments (6)
pages/dashboard/location/[slug]/edit.vue (1)

1-3: Add TODO comments or basic implementation structure.

This placeholder page lacks any indication of planned functionality or implementation details. Consider adding TODO comments describing the expected features or a basic component structure to guide future development.

 <template>
-  <h2>Location edit page</h2>
+  <!-- TODO: Implement location edit form -->
+  <!-- Features needed: location name, description, coordinates editing -->
+  <div>
+    <h2>Edit Location</h2>
+    <!-- TODO: Add location edit form here -->
+  </div>
 </template>
pages/dashboard/location/[slug]/add.vue (1)

1-3: Add implementation guidance and clarify purpose.

This placeholder needs TODO comments describing the expected functionality for adding location logs. Consider adding basic structure and clarifying the relationship to the parent location.

 <template>
-  <h2>Location Log add page</h2>
+  <!-- TODO: Implement location log creation form -->
+  <!-- Features needed: log entry form, date picker, notes, images -->
+  <div>
+    <h2>Add Location Log</h2>
+    <!-- TODO: Add form to create new log entry for this location -->
+    <!-- TODO: Include location context (show current location name) -->
+  </div>
 </template>
lib/db/queries/location.ts (1)

11-21: Well-implemented secure query with good performance characteristics.

The function properly:

  • Uses parameterized queries to prevent SQL injection
  • Filters by both slug AND userId for proper authorization
  • Eager loads related locationLogs efficiently in a single query
  • Leverages Drizzle's type-safe query builder

Consider adding a JSDoc comment to document the return behavior when no location is found:

+/**
+ * Find a location by slug for a specific user, including associated logs
+ * @param slug - The location slug to search for
+ * @param userId - The user ID to filter by
+ * @returns The location with logs, or undefined if not found
+ */
 export async function findLocation(slug: string, userId: number) {
stores/sidebar.ts (1)

15-15: Fix naming convention inconsistency.

The SidebarTopItems variable uses PascalCase while sidebarItems uses camelCase. Consider renaming to sidebarTopItems for consistency.

-  const SidebarTopItems = ref<SidebarItem[]> ([]);
+  const sidebarTopItems = ref<SidebarItem[]>([]);
-    SidebarTopItems,
+    sidebarTopItems,

Also applies to: 19-19

pages/dashboard.vue (1)

15-75: Consider using watchEffect instead of effect

The effect() API is a low-level primitive. For this use case, watchEffect() would be more appropriate and provide better developer experience.

-effect(() => {
+watchEffect(() => {
   if (route.name === "dashboard") {
stores/locations.ts (1)

41-65: Consider optimizing reactive updates

The effect recreates all sidebar items and map points on every route change, which could impact performance with many locations.

Consider:

  1. Using computed properties for derived state
  2. Memoizing the location transformations
  3. Only updating when the route group changes (not every route change)

Example approach:

const shouldShowLocationsList = computed(() => 
  listLocationsInSidebar.has(route.name?.toString() || "")
);

const locationSidebarItems = computed(() => {
  if (!shouldShowLocationsList.value || !locations.value) return [];
  // transformation logic here
});
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 51154ae and 0a6dcf7.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (17)
  • components/app/map.client.vue (2 hunks)
  • components/sidebar-button.vue (2 hunks)
  • lib/db/queries/location.ts (1 hunks)
  • lib/db/schema/location-log.ts (2 hunks)
  • lib/db/schema/location.ts (3 hunks)
  • lib/types.ts (2 hunks)
  • package.json (2 hunks)
  • pages/dashboard.vue (3 hunks)
  • pages/dashboard/index.vue (2 hunks)
  • pages/dashboard/location/[slug].vue (1 hunks)
  • pages/dashboard/location/[slug]/add.vue (1 hunks)
  • pages/dashboard/location/[slug]/edit.vue (1 hunks)
  • server/api/locations/[slug].get.ts (1 hunks)
  • stores/locations.ts (1 hunks)
  • stores/map.ts (1 hunks)
  • stores/sidebar.ts (1 hunks)
  • utils/map-points.ts (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Socket Security: Pull Request Alerts
🔇 Additional comments (22)
package.json (2)

11-11: LGTM!

The typecheck script addition using nuxi typecheck is appropriate for enabling TypeScript validation in the project.


53-53: LGTM!

The vue-tsc dependency addition supports the TypeScript tooling improvements and the version ^3.0.5 is current and appropriate.

lib/types.ts (2)

1-1: LGTM!

The import of RouteLocationRaw from vue-router is correctly typed and necessary for the navigation enhancements.


19-20: LGTM!

The optional to and toLabel properties on MapPoint are well-designed, enabling navigation functionality while maintaining backward compatibility through optional typing.

stores/map.ts (2)

25-28: Good addition of maxZoom constraint.

Adding maxZoom: 10 to fitBounds prevents excessive zooming when fitting bounds around closely located points, improving user experience.


35-40: Animation improvements enhance map transitions.

The slower animation speed (0.2 vs previous 0.8) and linear easing function provide smoother, more controlled map transitions. The essential: true flag ensures the animation completes even during user interactions.

lib/db/schema/location-log.ts (2)

21-26: Database relation correctly established.

The locationLogRelation properly defines the one-to-one relationship from locationLog to location using the locationId foreign key. This complements the reciprocal relation and enables eager loading of related data.


28-28: Type export follows Drizzle ORM conventions.

The SelectLocationLog type export using $inferSelect is the standard pattern for creating TypeScript types from Drizzle schemas.

components/app/map.client.vue (1)

93-101: Excellent navigation enhancement in map popups.

The conditional rendering of NuxtLink buttons in map popups when points have navigation properties provides intuitive navigation directly from the map interface. This aligns well with the PR's goal of improving navigation.

server/api/locations/[slug].get.ts (1)

4-15: Well-structured authenticated API endpoint.

The implementation properly:

  • Extracts the slug parameter from the route
  • Ensures authentication via the wrapper function
  • Queries with both slug and user ID for security
  • Handles the not-found case with appropriate 404 response
  • Returns the location data with related logs
stores/sidebar.ts (1)

1-1: LGTM! Enhanced navigation flexibility.

The addition of RouteLocationRaw import and the updated SidebarItem type provide flexible navigation options. Making href optional while adding to allows components to use either traditional links or Vue Router navigation objects. The rename from location to mapPoint better reflects the data structure's purpose.

Also applies to: 9-11

pages/dashboard/location/[slug].vue (2)

1-7: LGTM! Proper Vue 3 Composition API usage.

The script setup correctly uses storeToRefs to maintain reactivity and properly triggers location refresh on component mount.


31-36: LGTM! Appropriate error handling.

The error state handling correctly shows only when there's an error and loading is complete. The alert styling and error message display are appropriate.

utils/map-points.ts (2)

4-10: LGTM! Well-designed conversion utility.

This function properly converts a SelectLocation to a MapPoint by spreading the location properties and adding the necessary routing metadata. The route structure aligns with the dashboard navigation pattern.


12-18: LGTM! Robust point comparison utility.

The function properly handles null/undefined cases and compares the essential identifying fields. Using Pick for the type parameter provides good flexibility while ensuring type safety.

pages/dashboard/index.vue (3)

3-3: LGTM! Improved naming consistency.

The renaming to locationsStatus and refreshLocations() improves clarity and aligns with the store's updated API. Using the alias maintains template compatibility.

Also applies to: 6-6


11-11: LGTM! UI consistency improvement.

Adding min-h-64 ensures consistent minimum height for the dashboard layout.


19-39: LGTM! Enhanced navigation and selection logic.

The conversion from div to NuxtLink enables proper navigation to individual location pages, fulfilling the PR objectives. The use of utility functions (isPointSelected and createMapPointFromLocation) improves code consistency and maintainability. The mouse event handlers properly manage map point selection.

lib/db/schema/location.ts (3)

3-3: LGTM! Necessary imports for relational setup.

The added imports are required for establishing the database relations and type definitions. All imports are properly utilized in the code.

Also applies to: 7-7, 10-10


24-26: LGTM! Correct relational mapping.

The locationRelation properly defines the one-to-many relationship between locations and location logs using Drizzle ORM's relations syntax.


42-45: LGTM! Well-structured type definitions.

The SelectLocation type properly uses Drizzle's $inferSelect, and SelectLocationWithLogs correctly extends it with the related logs array. This provides good type safety for queries that include related data.

stores/locations.ts (1)

27-37: No missing fetch trigger—refreshCurrentLocation is called in the page

The store defines refreshCurrentLocation with immediate: false and watch: false, but the page at

  • pages/dashboard/location/[slug].vue

explicitly invokes:

locationStore.refreshCurrentLocation();

so the fetch will run as intended.

Likely an incorrect or invalid review comment.

@@ -71,15 +71,15 @@ onMounted(() => {
class="tooltip tooltip-top hover:cursor-pointer"
:data-tip="point.name"
:class="{
'tooltip-open': point === mapStore.selectedPoint,
'tooltip-open': isPointSelected(point, mapStore.selectedPoint),
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Missing import for isPointSelected utility function.

The code uses isPointSelected function but I don't see it imported. This will cause a runtime error.

Add the missing import at the top of the script section:

 import { CENTER_USA } from "~/lib/constant";
 import { useMapStore } from "~/stores/map";
+import { isPointSelected } from "~/utils/map-points";

Also applies to: 82-82

🤖 Prompt for AI Agents
In components/app/map.client.vue at lines 74 and 82, the function
isPointSelected is used but not imported, which will cause a runtime error. To
fix this, add an import statement for isPointSelected at the top of the script
section, importing it from its correct module or utility file where it is
defined.

@@ -17,7 +20,7 @@ const route = useRoute();
:class="{ tooltip: !showLabel }"
>
<NuxtLink
:to="props.href"
:to="props.href || props.to"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Potential issue with href/to prop handling.

Using props.href || props.to could cause unexpected behavior if href is an empty string (falsy), as it would fallback to the to prop. Consider using nullish coalescing instead.

-      :to="props.href || props.to"
+      :to="props.href ?? props.to"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
:to="props.href || props.to"
:to="props.href ?? props.to"
🤖 Prompt for AI Agents
In components/sidebar-button.vue at line 23, the expression uses `props.href ||
props.to` which can incorrectly fallback to `props.to` if `props.href` is an
empty string. Replace the logical OR with the nullish coalescing operator `??`
to ensure that only null or undefined values trigger the fallback, preserving
empty string values correctly.

@@ -17,7 +20,7 @@ const route = useRoute();
:class="{ tooltip: !showLabel }"
>
<NuxtLink
:to="props.href"
:to="props.href || props.to"
:class="{ 'bg-base-200': route.path === props.href, 'justify-center': !props.showLabel, 'justify-start': props.showLabel }"
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Active route highlighting only works for href prop.

The active route check route.path === props.href won't work for routes specified via the to prop, meaning those navigation items won't show as active.

Consider updating the active check to handle both cases:

-      :class="{ 'bg-base-200': route.path === props.href, 'justify-center': !props.showLabel, 'justify-start': props.showLabel }"
+      :class="{ 'bg-base-200': route.path === (props.href ?? (typeof props.to === 'string' ? props.to : props.to?.path)), 'justify-center': !props.showLabel, 'justify-start': props.showLabel }"

Or create a computed property to handle the active state logic more cleanly.

🤖 Prompt for AI Agents
In components/sidebar-button.vue at line 24, the active route highlighting only
checks if route.path equals props.href, which misses cases where navigation uses
the to prop. Update the active check to consider both props.href and props.to by
comparing route.path to either value, or better, create a computed property that
returns true if route.path matches either props.href or props.to, and use that
computed property in the class binding for cleaner and more accurate active
state handling.

Comment on lines +33 to +50
sidebarStore.SidebarTopItems = [
{
id: "link-dashboard",
label: "Back to Locations",
icon: "tabler:arrow-back",
href: "/dashboard",
},
{
id: "link-dashboard",
label: currentLocation.value ? currentLocation.value.name : "View Logs",
icon: "tabler:map",
to: {
name: "dashboard-location-slug",
params: {
slug: currentLocation.value?.slug,
},
},
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix duplicate sidebar item IDs

Multiple sidebar items have the same ID "link-dashboard" (lines 35 and 41), which will cause key conflicts in Vue's rendering system.

       {
-        id: "link-dashboard",
+        id: "link-location-view",
         label: currentLocation.value ? currentLocation.value.name : "View Logs",
         icon: "tabler:map",
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
sidebarStore.SidebarTopItems = [
{
id: "link-dashboard",
label: "Back to Locations",
icon: "tabler:arrow-back",
href: "/dashboard",
},
{
id: "link-dashboard",
label: currentLocation.value ? currentLocation.value.name : "View Logs",
icon: "tabler:map",
to: {
name: "dashboard-location-slug",
params: {
slug: currentLocation.value?.slug,
},
},
},
sidebarStore.SidebarTopItems = [
{
id: "link-dashboard",
label: "Back to Locations",
icon: "tabler:arrow-back",
href: "/dashboard",
},
{
id: "link-location-view",
label: currentLocation.value ? currentLocation.value.name : "View Logs",
icon: "tabler:map",
to: {
name: "dashboard-location-slug",
params: {
slug: currentLocation.value?.slug,
},
},
},
🤖 Prompt for AI Agents
In pages/dashboard.vue between lines 33 and 50, the sidebar items have duplicate
IDs "link-dashboard" which causes key conflicts in Vue rendering. Update the
second item's ID to a unique value, such as "link-location" or another
descriptive identifier, to ensure each sidebar item has a distinct ID.

Comment on lines +42 to +49
label: currentLocation.value ? currentLocation.value.name : "View Logs",
icon: "tabler:map",
to: {
name: "dashboard-location-slug",
params: {
slug: currentLocation.value?.slug,
},
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Add null safety guards for navigation parameters

While optional chaining is used for slug, passing undefined to route params could cause navigation issues.

         label: currentLocation.value ? currentLocation.value.name : "View Logs",
         icon: "tabler:map",
-        to: {
+        to: currentLocation.value?.slug ? {
           name: "dashboard-location-slug",
           params: {
             slug: currentLocation.value?.slug,
           },
-        },
+        } : undefined,

Apply similar guards to the other navigation objects in lines 55-60 and 67-72.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
label: currentLocation.value ? currentLocation.value.name : "View Logs",
icon: "tabler:map",
to: {
name: "dashboard-location-slug",
params: {
slug: currentLocation.value?.slug,
},
},
label: currentLocation.value ? currentLocation.value.name : "View Logs",
icon: "tabler:map",
to: currentLocation.value?.slug ? {
name: "dashboard-location-slug",
params: {
slug: currentLocation.value?.slug,
},
} : undefined,
🤖 Prompt for AI Agents
In pages/dashboard.vue around lines 42 to 49, the navigation parameter slug uses
optional chaining which may pass undefined to route params causing navigation
issues. Add explicit null safety checks to ensure slug is defined before passing
it, and apply the same null safety guards to the navigation objects in lines
55-60 and 67-72 to prevent undefined values in route params.

Comment on lines 21 to 29
<div v-if="!location.locationLogs.length" class="mt-4">
<p class="text-sm italic">
Add a location log to get started.
</p>
<button class="btn btn-primary bt-sm mt-2">
Add Location Log
<Icon name="tabler:map-pin-plus" size="24" />
</button>
</div>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix typo and add navigation functionality.

There's a CSS class typo and the button lacks navigation functionality:

  1. Line 25: bt-sm should be btn-sm
  2. The "Add Location Log" button needs a click handler or navigation to actually add logs
-        <button class="btn btn-primary bt-sm mt-2">
+        <button class="btn btn-primary btn-sm mt-2" @click="navigateToAddLog">
           Add Location Log
           <Icon name="tabler:map-pin-plus" size="24" />
         </button>

Consider adding a navigation method in the script section:

const router = useRouter();
const route = useRoute();

const navigateToAddLog = () => {
  router.push(`/dashboard/location/${route.params.slug}/add`);
};
🤖 Prompt for AI Agents
In pages/dashboard/location/[slug].vue around lines 21 to 29, fix the typo in
the button's CSS class by changing "bt-sm" to "btn-sm". Additionally, add a
click handler to the "Add Location Log" button that triggers navigation to the
add log page. Implement a navigation method in the script section using
useRouter and useRoute to push to `/dashboard/location/${route.params.slug}/add`
when the button is clicked.

Comment on lines 45 to 56
locations.value.forEach((location) => {
const mapPoint = createMapPointFromLocation(location);
mapPoints.push(mapPoint);
SidebarItems.push({
id: `location-${location.id}`,
label: location.name,
icon: "tabler:map-pin-filled",
to: { name: "dashboard-location-slug", params: { slug: location.slug } },
mapPoint,
});
mapPoints.push(mapPoint);
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Remove duplicate mapPoints.push call

Each location is being pushed to mapPoints twice, which will cause duplicate markers on the map.

       locations.value.forEach((location) => {
         const mapPoint = createMapPointFromLocation(location);
         mapPoints.push(mapPoint);
         SidebarItems.push({
           id: `location-${location.id}`,
           label: location.name,
           icon: "tabler:map-pin-filled",
           to: { name: "dashboard-location-slug", params: { slug: location.slug } },
           mapPoint,
         });
-        mapPoints.push(mapPoint);
       });
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
locations.value.forEach((location) => {
const mapPoint = createMapPointFromLocation(location);
mapPoints.push(mapPoint);
SidebarItems.push({
id: `location-${location.id}`,
label: location.name,
icon: "tabler:map-pin-filled",
to: { name: "dashboard-location-slug", params: { slug: location.slug } },
mapPoint,
});
mapPoints.push(mapPoint);
});
locations.value.forEach((location) => {
const mapPoint = createMapPointFromLocation(location);
mapPoints.push(mapPoint);
SidebarItems.push({
id: `location-${location.id}`,
label: location.name,
icon: "tabler:map-pin-filled",
to: { name: "dashboard-location-slug", params: { slug: location.slug } },
mapPoint,
});
});
🤖 Prompt for AI Agents
In stores/locations.ts between lines 45 and 56, the mapPoints array has
duplicate entries because mapPoints.push(mapPoint) is called twice for each
location. Remove the second mapPoints.push(mapPoint) call inside the forEach
loop to prevent duplicate markers on the map.

Comment on lines 60 to 63
else if (currentLocation.value && listCurrentLocationLogsInSidebar.has(route.name?.toString() || "")) {
sidebarStore.sidebarItems = [];
mapStore.mapPoints = [currentLocation.value];
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix type mismatch for mapPoints assignment

mapPoints expects an array of MapPoint objects, but currentLocation.value is being assigned directly without transformation.

     else if (currentLocation.value && listCurrentLocationLogsInSidebar.has(route.name?.toString() || "")) {
       sidebarStore.sidebarItems = [];
-      mapStore.mapPoints = [currentLocation.value];
+      mapStore.mapPoints = [createMapPointFromLocation(currentLocation.value)];
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
else if (currentLocation.value && listCurrentLocationLogsInSidebar.has(route.name?.toString() || "")) {
sidebarStore.sidebarItems = [];
mapStore.mapPoints = [currentLocation.value];
}
else if (currentLocation.value && listCurrentLocationLogsInSidebar.has(route.name?.toString() || "")) {
sidebarStore.sidebarItems = [];
mapStore.mapPoints = [createMapPointFromLocation(currentLocation.value)];
}
🤖 Prompt for AI Agents
In stores/locations.ts around lines 60 to 63, the assignment to
mapStore.mapPoints is incorrect because currentLocation.value is not directly a
MapPoint object. To fix this, transform currentLocation.value into a MapPoint
object or wrap it properly so that mapPoints receives an array of MapPoint
instances as expected. Ensure the assigned array matches the MapPoint type
definition.

@timDeHof timDeHof merged commit 2e308ce into main Aug 5, 2025
7 checks passed
@timDeHof timDeHof deleted the ntl-32 branch August 5, 2025 04:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

As a traveler, I want to I want to see location specific links in the sidebar
1 participant