Merge pull request #253 from trails-cool/feat/route-empty-state-cta
Show empty-state CTA on Route detail when no waypoints
This commit is contained in:
commit
29cbcef844
3 changed files with 49 additions and 1 deletions
|
|
@ -99,6 +99,11 @@ export default function RouteDetailPage({ loaderData }: Route.ComponentProps) {
|
||||||
const [editLoading, setEditLoading] = useState(false);
|
const [editLoading, setEditLoading] = useState(false);
|
||||||
const [highlightedDay, setHighlightedDay] = useState<number | null>(null);
|
const [highlightedDay, setHighlightedDay] = useState<number | null>(null);
|
||||||
|
|
||||||
|
// A route is "empty" when it has no geometry and no computed distance —
|
||||||
|
// i.e. nobody has planned any waypoints yet. Surfaced as a dedicated
|
||||||
|
// empty-state below so the page isn't a dead end.
|
||||||
|
const isEmpty = !route.geojson && route.distance == null;
|
||||||
|
|
||||||
const handleEditInPlanner = useCallback(async () => {
|
const handleEditInPlanner = useCallback(async () => {
|
||||||
setEditLoading(true);
|
setEditLoading(true);
|
||||||
try {
|
try {
|
||||||
|
|
@ -121,7 +126,7 @@ export default function RouteDetailPage({ loaderData }: Route.ComponentProps) {
|
||||||
<p className="mt-2 text-gray-600">{route.description}</p>
|
<p className="mt-2 text-gray-600">{route.description}</p>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{isOwner && (
|
{isOwner && !isEmpty && (
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2">
|
||||||
<button
|
<button
|
||||||
onClick={handleEditInPlanner}
|
onClick={handleEditInPlanner}
|
||||||
|
|
@ -222,6 +227,35 @@ export default function RouteDetailPage({ loaderData }: Route.ComponentProps) {
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
{isEmpty && (
|
||||||
|
<div className="mt-6 flex flex-col items-center rounded-lg border border-dashed border-gray-300 bg-gray-50 px-6 py-12 text-center">
|
||||||
|
<div className="text-4xl" aria-hidden="true">🗺️</div>
|
||||||
|
<h2 className="mt-4 text-lg font-semibold text-gray-900">
|
||||||
|
{t("routes.empty.heading")}
|
||||||
|
</h2>
|
||||||
|
<p className="mt-2 max-w-md text-sm text-gray-600">
|
||||||
|
{isOwner ? t("routes.empty.bodyOwner") : t("routes.empty.bodyViewer")}
|
||||||
|
</p>
|
||||||
|
{isOwner && (
|
||||||
|
<div className="mt-6 flex flex-wrap items-center justify-center gap-3">
|
||||||
|
<button
|
||||||
|
onClick={handleEditInPlanner}
|
||||||
|
disabled={editLoading}
|
||||||
|
className="rounded-md bg-blue-600 px-4 py-2 text-sm font-medium text-white hover:bg-blue-700 disabled:opacity-50"
|
||||||
|
>
|
||||||
|
{editLoading ? t("routes.opening") : t("routes.empty.openInPlanner")}
|
||||||
|
</button>
|
||||||
|
<a
|
||||||
|
href={`/routes/${route.id}/edit`}
|
||||||
|
className="text-sm text-gray-600 underline hover:text-gray-900"
|
||||||
|
>
|
||||||
|
{t("routes.empty.uploadGpx")}
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{versions.length > 0 && (
|
{versions.length > 0 && (
|
||||||
<div className="mt-8">
|
<div className="mt-8">
|
||||||
<h2 className="text-lg font-semibold text-gray-900">Version History</h2>
|
<h2 className="text-lg font-semibold text-gray-900">Version History</h2>
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,13 @@ export default {
|
||||||
noRoutesYet: "Noch keine Routen. Erstelle deine erste Route!",
|
noRoutesYet: "Noch keine Routen. Erstelle deine erste Route!",
|
||||||
noMapPreview: "Keine Kartenvorschau",
|
noMapPreview: "Keine Kartenvorschau",
|
||||||
saveChanges: "Änderungen speichern",
|
saveChanges: "Änderungen speichern",
|
||||||
|
empty: {
|
||||||
|
heading: "Diese Route ist leer",
|
||||||
|
bodyOwner: "Du hast noch keine Wegpunkte geplant. Öffne sie im Planer, um eine Strecke zu skizzieren, oder lade eine GPX-Datei hoch.",
|
||||||
|
bodyViewer: "Diese Route enthält noch keine Wegpunkte.",
|
||||||
|
openInPlanner: "Im Planer öffnen",
|
||||||
|
uploadGpx: "oder eine GPX-Datei hochladen",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
activities: {
|
activities: {
|
||||||
title: "Aktivitäten",
|
title: "Aktivitäten",
|
||||||
|
|
|
||||||
|
|
@ -179,6 +179,13 @@ export default {
|
||||||
noRoutesYet: "No routes yet. Create your first route!",
|
noRoutesYet: "No routes yet. Create your first route!",
|
||||||
noMapPreview: "No map preview",
|
noMapPreview: "No map preview",
|
||||||
saveChanges: "Save Changes",
|
saveChanges: "Save Changes",
|
||||||
|
empty: {
|
||||||
|
heading: "This route is empty",
|
||||||
|
bodyOwner: "You haven't planned any waypoints yet. Open it in the Planner to sketch a path, or upload a GPX file.",
|
||||||
|
bodyViewer: "This route doesn't have any waypoints yet.",
|
||||||
|
openInPlanner: "Open in Planner",
|
||||||
|
uploadGpx: "or upload a GPX file",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
activities: {
|
activities: {
|
||||||
title: "Activities",
|
title: "Activities",
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue