only for login user access pages condition updated for homw page and crawl page and logout function updated

This commit is contained in:
Alaguraj0361 2025-09-18 13:38:03 +05:30
parent 3cdab23587
commit 290dff0b4a
8 changed files with 97 additions and 49 deletions

View File

@ -1,6 +1,7 @@
// app/(defaults)/crawl/page.tsx // app/(defaults)/crawl/page.tsx
'use client'; 'use client';
import { useRouter } from 'next/navigation';
import React, { useEffect, useMemo, useState } from 'react'; import React, { useEffect, useMemo, useState } from 'react';
/** /**
@ -29,6 +30,18 @@ export default function CrawlPage() {
const apiBase = 'https://api.crawlerx.co/crawl'; const apiBase = 'https://api.crawlerx.co/crawl';
const router = useRouter();
useEffect(() => {
const token = localStorage.getItem("token");
if (!token) {
// If no token, redirect to login page
router.push("/login");
}
}, [router]);
/* ---------------- URL helpers ---------------- */ /* ---------------- URL helpers ---------------- */
const isValidUrl = useMemo(() => { const isValidUrl = useMemo(() => {
try { try {
@ -104,28 +117,28 @@ export default function CrawlPage() {
URL.revokeObjectURL(url); URL.revokeObjectURL(url);
} }
function exportCSV() { function exportCSV() {
const rows = filteredRows; const rows = filteredRows;
if (!rows.length) return; if (!rows.length) return;
const cols = visibleCols.length ? visibleCols : defaultCols; const cols = visibleCols.length ? visibleCols : defaultCols;
const csvEscape = (v: any) => { const csvEscape = (v: any) => {
if (v == null) return ''; if (v == null) return '';
const s = String(v); const s = String(v);
// NOTE: keep this regex on one line! // NOTE: keep this regex on one line!
return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s; return /[",\n]/.test(s) ? `"${s.replace(/"/g, '""')}"` : s;
}; };
const header = cols.join(','); const header = cols.join(',');
const lines = rows.map((r) => cols.map((c) => csvEscape(r[c])).join(',')); const lines = rows.map((r) => cols.map((c) => csvEscape(r[c])).join(','));
const csv = [header, ...lines].join('\n'); const csv = [header, ...lines].join('\n');
const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' }); const blob = new Blob([csv], { type: 'text/csv;charset=utf-8' });
const a = document.createElement('a'); const a = document.createElement('a');
a.href = URL.createObjectURL(blob); a.href = URL.createObjectURL(blob);
a.download = 'crawl-report.csv'; a.download = 'crawl-report.csv';
a.click(); a.click();
} }
/* ---------------- data shaping ---------------- */ /* ---------------- data shaping ---------------- */
const rows = useMemo(() => dataRows(report), [report]); const rows = useMemo(() => dataRows(report), [report]);
@ -144,7 +157,7 @@ function exportCSV() {
useEffect(() => { useEffect(() => {
if (!rows.length) return; if (!rows.length) return;
if (!visibleCols.length) setVisibleCols(PRESets[view]?.columns ?? defaultCols); if (!visibleCols.length) setVisibleCols(PRESets[view]?.columns ?? defaultCols);
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
}, [rows.length]); }, [rows.length]);
// recompute on view change // recompute on view change
@ -422,8 +435,8 @@ function dataRows(report: any): any[] {
const data = Array.isArray(report) const data = Array.isArray(report)
? report ? report
: Array.isArray(report?.results) : Array.isArray(report?.results)
? report.results ? report.results
: null; : null;
return Array.isArray(data) ? data : []; return Array.isArray(data) ? data : [];
} }

View File

@ -1,12 +1,25 @@
import { Metadata } from 'next'; "use client";
import React from 'react';
export const metadata: Metadata = { // import { Metadata } from "next";
title: 'CrawlerX', import React, { useEffect } from "react";
}; import { useRouter } from "next/navigation";
// export const metadata: Metadata = {
// title: "CrawlerX",
// };
const Dashboard = () => { const Dashboard = () => {
return <div>starter page</div>; const router = useRouter();
useEffect(() => {
const token = localStorage.getItem("token");
if (!token) {
// If no token, redirect to login page
router.push("/login");
}
}, [router]);
return <div>starter page</div>;
}; };
export default Dashboard; export default Dashboard;

View File

@ -6,8 +6,8 @@ import { Nunito } from 'next/font/google';
export const metadata: Metadata = { export const metadata: Metadata = {
title: { title: {
template: '%s | VRISTO - Multipurpose Tailwind Dashboard Template', template: 'CrawlerX',
default: 'VRISTO - Multipurpose Tailwind Dashboard Template', default: 'Crawl Smarter. Rank Higher.',
}, },
}; };
const nunito = Nunito({ const nunito = Nunito({

View File

@ -1,6 +1,6 @@
const Footer = () => { const Footer = () => {
return ( return (
<div className="p-6 pt-0 mt-auto text-center dark:text-white-dark ltr:sm:text-left rtl:sm:text-right">© {new Date().getFullYear()}. Vristo All rights reserved.</div> <div className="p-6 pt-0 mt-auto text-center dark:text-white-dark ltr:sm:text-left rtl:sm:text-right">© {new Date().getFullYear()}. CrawlerX All rights reserved.</div>
); );
}; };

View File

@ -144,6 +144,17 @@ const Header = () => {
}; };
const [search, setSearch] = useState(false); const [search, setSearch] = useState(false);
const [token, setToken] = useState("")
useEffect(() => {
const Token: any = localStorage.getItem('token')
setToken(Token)
}, [])
const HandleLogout = () => {
localStorage.removeItem('token')
router.push('/login')
}
return ( return (
<header className={`z-40 ${themeConfig.semidark && themeConfig.menu === 'horizontal' ? 'dark' : ''}`}> <header className={`z-40 ${themeConfig.semidark && themeConfig.menu === 'horizontal' ? 'dark' : ''}`}>
@ -152,7 +163,7 @@ const Header = () => {
<div className="horizontal-logo flex items-center justify-between ltr:mr-2 rtl:ml-2 lg:hidden"> <div className="horizontal-logo flex items-center justify-between ltr:mr-2 rtl:ml-2 lg:hidden">
<Link href="/" className="main-logo flex shrink-0 items-center"> <Link href="/" className="main-logo flex shrink-0 items-center">
<img className="inline w-8 ltr:-ml-1 rtl:-mr-1" src="/assets/images/logo.svg" alt="logo" /> <img className="inline w-8 ltr:-ml-1 rtl:-mr-1" src="/assets/images/logo.svg" alt="logo" />
<span className="hidden align-middle text-2xl font-semibold transition-all duration-300 ltr:ml-1.5 rtl:mr-1.5 dark:text-white-light md:inline">VRISTO</span> <span className="hidden align-middle text-2xl font-semibold transition-all duration-300 ltr:ml-1.5 rtl:mr-1.5 dark:text-white-light md:inline">CrawlerX</span>
</Link> </Link>
<button <button
type="button" type="button"
@ -213,10 +224,9 @@ const Header = () => {
<div> <div>
{themeConfig.theme === 'light' ? ( {themeConfig.theme === 'light' ? (
<button <button
className={`${ className={`${themeConfig.theme === 'light' &&
themeConfig.theme === 'light' &&
'flex items-center rounded-full bg-white-light/40 p-2 hover:bg-white-light/90 hover:text-primary dark:bg-dark/40 dark:hover:bg-dark/60' 'flex items-center rounded-full bg-white-light/40 p-2 hover:bg-white-light/90 hover:text-primary dark:bg-dark/40 dark:hover:bg-dark/60'
}`} }`}
onClick={() => dispatch(toggleTheme('dark'))} onClick={() => dispatch(toggleTheme('dark'))}
> >
<IconSun /> <IconSun />
@ -226,10 +236,9 @@ const Header = () => {
)} )}
{themeConfig.theme === 'dark' && ( {themeConfig.theme === 'dark' && (
<button <button
className={`${ className={`${themeConfig.theme === 'dark' &&
themeConfig.theme === 'dark' &&
'flex items-center rounded-full bg-white-light/40 p-2 hover:bg-white-light/90 hover:text-primary dark:bg-dark/40 dark:hover:bg-dark/60' 'flex items-center rounded-full bg-white-light/40 p-2 hover:bg-white-light/90 hover:text-primary dark:bg-dark/40 dark:hover:bg-dark/60'
}`} }`}
onClick={() => dispatch(toggleTheme('system'))} onClick={() => dispatch(toggleTheme('system'))}
> >
<IconMoon /> <IconMoon />
@ -237,10 +246,9 @@ const Header = () => {
)} )}
{themeConfig.theme === 'system' && ( {themeConfig.theme === 'system' && (
<button <button
className={`${ className={`${themeConfig.theme === 'system' &&
themeConfig.theme === 'system' &&
'flex items-center rounded-full bg-white-light/40 p-2 hover:bg-white-light/90 hover:text-primary dark:bg-dark/40 dark:hover:bg-dark/60' 'flex items-center rounded-full bg-white-light/40 p-2 hover:bg-white-light/90 hover:text-primary dark:bg-dark/40 dark:hover:bg-dark/60'
}`} }`}
onClick={() => dispatch(toggleTheme('light'))} onClick={() => dispatch(toggleTheme('light'))}
> >
<IconLaptop /> <IconLaptop />
@ -445,10 +453,24 @@ const Header = () => {
</Link> </Link>
</li> </li>
<li className="border-t border-white-light dark:border-white-light/10"> <li className="border-t border-white-light dark:border-white-light/10">
<Link href="/auth/boxed-signin" className="!py-3 text-danger"> <li className="border-t border-white-light dark:border-white-light/10">
<IconLogout className="h-4.5 w-4.5 shrink-0 rotate-90 ltr:mr-2 rtl:ml-2" /> {token ? (
Sign Out <button
</Link> type="button"
onClick={HandleLogout}
className="!py-3 text-danger flex items-center"
>
<IconLogout className="h-4.5 w-4.5 shrink-0 rotate-90 ltr:mr-2 rtl:ml-2" />
Sign Out
</button>
) : (
<Link href="/login" className="!py-3 text-danger">
<IconLogout className="h-4.5 w-4.5 shrink-0 rotate-90 ltr:mr-2 rtl:ml-2" />
Login
</Link>
)}
</li>
</li> </li>
</ul> </ul>
</Dropdown> </Dropdown>

View File

@ -91,7 +91,7 @@ const Sidebar = () => {
<div className="flex items-center justify-between px-4 py-3"> <div className="flex items-center justify-between px-4 py-3">
<Link href="/" className="main-logo flex shrink-0 items-center"> <Link href="/" className="main-logo flex shrink-0 items-center">
<img className="ml-[5px] w-8 flex-none" src="/assets/images/logo.svg" alt="logo" /> <img className="ml-[5px] w-8 flex-none" src="/assets/images/logo.svg" alt="logo" />
<span className="align-middle text-2xl font-semibold ltr:ml-1.5 rtl:mr-1.5 dark:text-white-light lg:inline">VRISTO</span> <span className="align-middle text-2xl font-semibold ltr:ml-1.5 rtl:mr-1.5 dark:text-white-light lg:inline">CrawlerX</span>
</Link> </Link>
<button <button

4
package-lock.json generated
View File

@ -1,11 +1,11 @@
{ {
"name": "vristo-next", "name": "CrawlerX",
"version": "0.1.0", "version": "0.1.0",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "vristo-next", "name": "CrawlerX",
"version": "0.1.0", "version": "0.1.0",
"dependencies": { "dependencies": {
"@emotion/react": "^11.10.6", "@emotion/react": "^11.10.6",

View File

@ -1,5 +1,5 @@
{ {
"name": "vristo-next", "name": "crawlerx",
"version": "0.1.0", "version": "0.1.0",
"private": true, "private": true,
"scripts": { "scripts": {