fix: dead sidebar/wallet/leads/marketplace navigation links
Some checks failed
build-and-release / build (push) Failing after 1m11s
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:
parent
3d6a81d4ff
commit
474fa637c3
7 changed files with 112 additions and 8 deletions
|
|
@ -13,11 +13,11 @@ const SIDEBAR_ITEMS = [
|
||||||
|
|
||||||
const ROUTE_BY_LABEL: Record<string, string> = {
|
const ROUTE_BY_LABEL: Record<string, string> = {
|
||||||
"my dashboard": "/dashboard",
|
"my dashboard": "/dashboard",
|
||||||
leads: "/dashboard/leads",
|
leads: "/dashboard/leads/accepted",
|
||||||
"my requests": "/dashboard/requests",
|
"my requests": "/dashboard/requests",
|
||||||
credits: "/dashboard/credits",
|
credits: "/dashboard?nav=credits",
|
||||||
settings: "/dashboard/settings",
|
settings: "/dashboard?nav=settings",
|
||||||
logout: "/dashboard/logout",
|
logout: "/dashboard?nav=logout",
|
||||||
};
|
};
|
||||||
|
|
||||||
function readUserName() {
|
function readUserName() {
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ interface AcceptedLead {
|
||||||
accepted_at: string;
|
accepted_at: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function AcceptedLeadsPage() {
|
export default function AcceptedLeadsView() {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const params = useParams();
|
const params = useParams();
|
||||||
|
|
||||||
5
src/routes/dashboard/leads/accepted/[id].tsx
Normal file
5
src/routes/dashboard/leads/accepted/[id].tsx
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import AcceptedLeadsView from "~/components/dashboard/AcceptedLeadsView";
|
||||||
|
|
||||||
|
export default function AcceptedLeadDetailRoute() {
|
||||||
|
return <AcceptedLeadsView />;
|
||||||
|
}
|
||||||
5
src/routes/dashboard/leads/accepted/index.tsx
Normal file
5
src/routes/dashboard/leads/accepted/index.tsx
Normal file
|
|
@ -0,0 +1,5 @@
|
||||||
|
import AcceptedLeadsView from "~/components/dashboard/AcceptedLeadsView";
|
||||||
|
|
||||||
|
export default function AcceptedLeadsIndexRoute() {
|
||||||
|
return <AcceptedLeadsView />;
|
||||||
|
}
|
||||||
94
src/routes/dashboard/marketplace/[id].tsx
Normal file
94
src/routes/dashboard/marketplace/[id].tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -80,7 +80,7 @@ export default function BuyTracecoinsPage() {
|
||||||
|
|
||||||
setSuccess(true);
|
setSuccess(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
navigate("/dashboard/wallet");
|
navigate("/dashboard?nav=credits");
|
||||||
}, 2000);
|
}, 2000);
|
||||||
} catch (e: any) {
|
} catch (e: any) {
|
||||||
setError(e.message || "Payment failed. Please try again.");
|
setError(e.message || "Payment failed. Please try again.");
|
||||||
|
|
@ -173,7 +173,7 @@ export default function BuyTracecoinsPage() {
|
||||||
|
|
||||||
<div class="flex gap-4">
|
<div class="flex gap-4">
|
||||||
<button
|
<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"
|
class="flex-1 px-6 py-3 border border-gray-300 rounded-lg hover:bg-gray-50"
|
||||||
>
|
>
|
||||||
Cancel
|
Cancel
|
||||||
|
|
|
||||||
|
|
@ -79,7 +79,7 @@ export default function PayuReturnPage() {
|
||||||
if (res?.data?.verified) {
|
if (res?.data?.verified) {
|
||||||
setStatus("success");
|
setStatus("success");
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
navigate("/dashboard/wallet");
|
navigate("/dashboard?nav=credits");
|
||||||
}, 2500);
|
}, 2500);
|
||||||
} else {
|
} else {
|
||||||
setStatus("failure");
|
setStatus("failure");
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue