fix: dead sidebar/wallet/leads/marketplace navigation links
Some checks failed
build-and-release / build (push) Failing after 1m11s

- DashboardLayout sidebar: Leads/Credits/Settings/Logout pointed to
  routes with no matching file (404). Leads now routes to the real
  accepted-leads page; Credits/Settings/Logout reuse the working
  /dashboard?nav= deep-link into the main dashboard's tab switcher
  (fixes Logout leaving users authenticated on a 404).
- wallet/buy.tsx, wallet/payu-return.tsx: post-purchase, cancel, and
  payment-verification redirects targeted non-existent /dashboard/wallet;
  now redirect to the existing credits/wallet tab.
- leads/accepted.tsx already contained a detail view gated on
  useParams().id, but was only registered as a flat route with no :id
  segment, so the detail view was dead code. Split into
  leads/accepted/index.tsx + leads/accepted/[id].tsx backed by a shared
  AcceptedLeadsView component.
- Added marketplace/[id].tsx: "View Requirement" buttons navigated to
  a route that never existed.
This commit is contained in:
Ashwin Kumar Sivakumar 2026-07-12 17:58:37 +05:30
parent 3d6a81d4ff
commit 474fa637c3
7 changed files with 112 additions and 8 deletions

View file

@ -13,11 +13,11 @@ const SIDEBAR_ITEMS = [
const ROUTE_BY_LABEL: Record<string, string> = {
"my dashboard": "/dashboard",
leads: "/dashboard/leads",
leads: "/dashboard/leads/accepted",
"my requests": "/dashboard/requests",
credits: "/dashboard/credits",
settings: "/dashboard/settings",
logout: "/dashboard/logout",
credits: "/dashboard?nav=credits",
settings: "/dashboard?nav=settings",
logout: "/dashboard?nav=logout",
};
function readUserName() {

View file

@ -25,7 +25,7 @@ interface AcceptedLead {
accepted_at: string;
}
export default function AcceptedLeadsPage() {
export default function AcceptedLeadsView() {
const navigate = useNavigate();
const params = useParams();

View file

@ -0,0 +1,5 @@
import AcceptedLeadsView from "~/components/dashboard/AcceptedLeadsView";
export default function AcceptedLeadDetailRoute() {
return <AcceptedLeadsView />;
}

View file

@ -0,0 +1,5 @@
import AcceptedLeadsView from "~/components/dashboard/AcceptedLeadsView";
export default function AcceptedLeadsIndexRoute() {
return <AcceptedLeadsView />;
}

View file

@ -0,0 +1,94 @@
import { createResource, Show } from "solid-js";
import { useNavigate, useParams } from "@solidjs/router";
import DashboardLayout from "~/components/DashboardLayout";
import { RequireAuth } from "~/lib/auth";
import { apiFetch } from "~/lib/api";
export default function MarketplaceRequirementDetailRoute() {
const navigate = useNavigate();
const params = useParams();
const [requirement] = createResource(() => params.id, async (id) => {
return apiFetch(`/api/customers/requirements/${id}`);
});
const formatDate = (date: string) => {
return new Date(date).toLocaleDateString("en-IN", {
day: "numeric",
month: "long",
year: "numeric",
});
};
return (
<RequireAuth>
<DashboardLayout>
<div class="p-6 max-w-4xl mx-auto">
<button
onClick={() => navigate("/dashboard/marketplace")}
class="mb-4 text-gray-600 hover:text-gray-900 flex items-center gap-2"
>
Back to Marketplace
</button>
<Show when={requirement.loading}>
<div class="text-center py-12">
<div class="animate-spin w-8 h-8 border-2 border-orange-500 border-t-transparent rounded-full mx-auto mb-4" />
<p class="text-gray-500">Loading requirement...</p>
</div>
</Show>
<Show when={requirement.error}>
<div class="text-center py-12 bg-gray-50 rounded-xl">
<h3 class="text-lg font-semibold text-gray-700 mb-2">Requirement not found</h3>
<p class="text-gray-500">It may have been closed or removed.</p>
</div>
</Show>
<Show when={!requirement.loading && requirement()}>
{(req: any) => {
const r = req().data || req();
return (
<div class="bg-white border rounded-xl overflow-hidden">
<div class="bg-orange-50 p-6 border-b">
<h1 class="text-2xl font-bold text-gray-900">{r.title}</h1>
<p class="text-gray-600 mt-1">Posted on {r.created_at ? formatDate(r.created_at) : "—"}</p>
</div>
<div class="p-6 space-y-4">
<div>
<p class="text-sm text-gray-500">Service Type</p>
<p class="font-medium capitalize">
{(r.profession_key || "").toLowerCase().replace(/_/g, " ")}
</p>
</div>
<div>
<p class="text-sm text-gray-500">Location</p>
<p class="font-medium">{r.location}</p>
</div>
<div>
<p class="text-sm text-gray-500">Budget</p>
<p class="font-medium">
{r.budget?.toLocaleString() || "Not specified"}
</p>
</div>
<Show when={r.preferred_date}>
<div>
<p class="text-sm text-gray-500">Preferred Date</p>
<p class="font-medium">{formatDate(r.preferred_date)}</p>
</div>
</Show>
<div>
<p class="text-sm text-gray-500">Description</p>
<p class="text-gray-700 mt-1">{r.description}</p>
</div>
</div>
</div>
);
}}
</Show>
</div>
</DashboardLayout>
</RequireAuth>
);
}

View file

@ -80,7 +80,7 @@ export default function BuyTracecoinsPage() {
setSuccess(true);
setTimeout(() => {
navigate("/dashboard/wallet");
navigate("/dashboard?nav=credits");
}, 2000);
} catch (e: any) {
setError(e.message || "Payment failed. Please try again.");
@ -173,7 +173,7 @@ export default function BuyTracecoinsPage() {
<div class="flex gap-4">
<button
onClick={() => navigate("/dashboard/wallet")}
onClick={() => navigate("/dashboard?nav=credits")}
class="flex-1 px-6 py-3 border border-gray-300 rounded-lg hover:bg-gray-50"
>
Cancel

View file

@ -79,7 +79,7 @@ export default function PayuReturnPage() {
if (res?.data?.verified) {
setStatus("success");
setTimeout(() => {
navigate("/dashboard/wallet");
navigate("/dashboard?nav=credits");
}, 2500);
} else {
setStatus("failure");