- Add metadata to login and login-verify pages to prevent indexing. - Update robots.txt to disallow additional sensitive paths. - Enhance sitemap generation to filter by city and include accurate last modified dates. - Refactor canonical URL generation to support multi-domain architecture, ensuring self-canonicalization for city domains. - Remove deprecated CanonicalHandler component and streamline canonical URL handling. - Introduce safe JSON-LD output to prevent XSS vulnerabilities. - Add payment layout with appropriate metadata to prevent indexing. - Conduct a comprehensive technical SEO audit and implement necessary fixes across the application.
70 lines
2.5 KiB
JavaScript
70 lines
2.5 KiB
JavaScript
import Content from "@/components/dashboard/Content";
|
|
import { defineAbilitiesFor } from "@/lib/ability";
|
|
import { getUser } from "@/lib/auth";
|
|
import { getStateInfo } from "@/lib/getStateInfo";
|
|
import { removeToken } from "@/utils";
|
|
import { cookies } from "next/headers";
|
|
import { redirect } from "next/navigation";
|
|
import { fetchReq } from "@/lib/req";
|
|
import { rialToToman } from "@/lib/money";
|
|
import { safeJsonParse } from "@/lib/sanitize";
|
|
import { buildPatientUser } from "@/lib/representationAdapters";
|
|
import { getServerAccessToken } from "@/lib/serverToken";
|
|
|
|
export const metadata = {
|
|
robots: { index: false, follow: false },
|
|
};
|
|
|
|
export default async function Dashboard({ searchParams }) {
|
|
const awaitedSearchParams = await searchParams;
|
|
const { matchedCity } = await getStateInfo();
|
|
const user = await getUser();
|
|
|
|
const ability = defineAbilitiesFor(user);
|
|
const cookieStore = await cookies();
|
|
const token = await getServerAccessToken();
|
|
|
|
if (!ability.can("access", "Dashboard") || !token) {
|
|
removeToken();
|
|
return redirect("/login");
|
|
}
|
|
|
|
// The userInfo cookie holds the real user uuid; the standalone `uuid` cookie
|
|
// may still carry the OTP uuid, which 404s against user-profile.
|
|
const userInfo = safeJsonParse(cookieStore.get("userInfo")?.value);
|
|
const userUuid = userInfo?.uuid || cookieStore.get("uuid")?.value;
|
|
const authHeader = { headers: { Authorization: `Bearer ${token}` } };
|
|
const API = process.env.NEXT_PUBLIC_API_URL;
|
|
|
|
const [profile, appointmentsRes, paymentsRes] = await Promise.all([
|
|
userUuid
|
|
? fetchReq(`${API}/api/v1/user-profile/${userUuid}`, authHeader)
|
|
: Promise.resolve(null),
|
|
fetchReq(`${API}/api/v1/my/appointments?page=1&limit=1`, authHeader),
|
|
fetchReq(`${API}/api/v1/my/payments?page=1&limit=200`, authHeader),
|
|
]);
|
|
|
|
const numberOfTurns = appointmentsRes?.meta?.totalRecords ?? 0;
|
|
const payments = paymentsRes?.data ?? [];
|
|
const totalRials = payments
|
|
.filter((p) => p.status === "success")
|
|
.reduce((sum, p) => sum + (Number(p.amount_rials) || 0), 0);
|
|
const totalTransactions = rialToToman(totalRials); // ریال → تومان
|
|
|
|
const extras = {
|
|
mobile: userInfo?.mobile_number ?? "",
|
|
realName: userInfo?.realName ?? "",
|
|
number_of_turns: numberOfTurns,
|
|
total_transactions: totalTransactions,
|
|
};
|
|
|
|
return (
|
|
<Content
|
|
logged={true}
|
|
params={awaitedSearchParams}
|
|
matchedCity={matchedCity}
|
|
user={buildPatientUser(profile, extras)}
|
|
/>
|
|
);
|
|
}
|