Compare commits

...

1 Commits

Author SHA1 Message Date
Flatlogic Bot
f0db2f75a1 Version 1.0 2026-02-01 11:31:54 +00:00

View File

@ -1,166 +1,305 @@
import React, { useEffect, useState } from 'react';
import type { ReactElement } from 'react';
import Head from 'next/head';
import Link from 'next/link';
import { useRouter } from 'next/router';
import * as icon from '@mdi/js';
import BaseIcon from '../components/BaseIcon';
import BaseButton from '../components/BaseButton';
import CardBox from '../components/CardBox';
import SectionFullScreen from '../components/SectionFullScreen';
import LayoutGuest from '../layouts/Guest';
import BaseDivider from '../components/BaseDivider';
import BaseButtons from '../components/BaseButtons';
import { getPageTitle } from '../config';
import { useAppSelector } from '../stores/hooks';
import CardBoxComponentTitle from "../components/CardBoxComponentTitle";
import { getPexelsImage, getPexelsVideo } from '../helpers/pexels';
import { useAppDispatch, useAppSelector } from '../stores/hooks';
import { fetch as fetchDevices } from '../stores/devices/devicesSlice';
export default function LandingPage() {
const router = useRouter();
const dispatch = useAppDispatch();
const { currentUser } = useAppSelector((state) => state.auth);
const { devices, loading: devicesLoading } = useAppSelector((state) => state.devices);
const darkMode = useAppSelector((state) => state.style.darkMode);
export default function Starter() {
const [illustrationImage, setIllustrationImage] = useState({
src: undefined,
photographer: undefined,
photographer_url: undefined,
})
const [illustrationVideo, setIllustrationVideo] = useState({video_files: []})
const [contentType, setContentType] = useState('video');
const [contentPosition, setContentPosition] = useState('right');
const textColor = useAppSelector((state) => state.style.linkColor);
const [activeTab, setActiveTab] = useState('pc');
const title = 'App Draft'
useEffect(() => {
if (currentUser) {
dispatch(fetchDevices({ query: '?limit=5' }));
}
}, [currentUser, dispatch]);
// Fetch Pexels image/video
useEffect(() => {
async function fetchData() {
const image = await getPexelsImage();
const video = await getPexelsVideo();
setIllustrationImage(image);
setIllustrationVideo(video);
}
fetchData();
}, []);
const imageBlock = (image) => (
<div
className='hidden md:flex flex-col justify-end relative flex-grow-0 flex-shrink-0 w-1/3'
style={{
backgroundImage: `${
image
? `url(${image?.src?.original})`
: 'linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5))'
}`,
backgroundSize: 'cover',
backgroundPosition: 'left center',
backgroundRepeat: 'no-repeat',
}}
>
<div className='flex justify-center w-full bg-blue-300/20'>
<a
className='text-[8px]'
href={image?.photographer_url}
target='_blank'
rel='noreferrer'
>
Photo by {image?.photographer} on Pexels
</a>
</div>
</div>
);
const videoBlock = (video) => {
if (video?.video_files?.length > 0) {
return (
<div className='hidden md:flex flex-col justify-end relative flex-grow-0 flex-shrink-0 w-1/3'>
<video
className='absolute top-0 left-0 w-full h-full object-cover'
autoPlay
loop
muted
>
<source src={video?.video_files[0]?.link} type='video/mp4'/>
Your browser does not support the video tag.
</video>
<div className='flex justify-center w-full bg-blue-300/20 z-10'>
<a
className='text-[8px]'
href={video?.user?.url}
target='_blank'
rel='noreferrer'
>
Video by {video.user.name} on Pexels
</a>
</div>
</div>)
}
};
const features = [
{
title: 'Real-time Protection',
description: 'Continuous monitoring for malware, viruses, and suspicious activities across all your platforms.',
icon: icon.mdiShieldCheck,
color: 'text-emerald-500',
},
{
title: 'Cross-Device Sync',
description: 'Connect your PC and Android devices seamlessly. Share security status and alerts instantly.',
icon: icon.mdiSync,
color: 'text-indigo-500',
},
{
title: 'Remote Scan',
description: 'Trigger a full system scan on your PC directly from your Android phone, or vice-versa.',
icon: icon.mdiShieldSearch,
color: 'text-blue-500',
},
{
title: 'Privacy Guard',
description: 'Protect your sensitive data with advanced encryption and privacy-focused browsing tools.',
icon: icon.mdiLock,
color: 'text-amber-500',
},
];
return (
<div
style={
contentPosition === 'background'
? {
backgroundImage: `${
illustrationImage
? `url(${illustrationImage.src?.original})`
: 'linear-gradient(rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.5))'
}`,
backgroundSize: 'cover',
backgroundPosition: 'left center',
backgroundRepeat: 'no-repeat',
}
: {}
}
>
<div className={`min-h-screen ${darkMode ? 'bg-slate-900 text-white' : 'bg-slate-50 text-slate-900'}`}>
<Head>
<title>{getPageTitle('Starter Page')}</title>
<title>{getPageTitle('SecureGuard - Ultimate Multi-Device Security')}</title>
</Head>
<SectionFullScreen bg='violet'>
<div
className={`flex ${
contentPosition === 'right' ? 'flex-row-reverse' : 'flex-row'
} min-h-screen w-full`}
>
{contentType === 'image' && contentPosition !== 'background'
? imageBlock(illustrationImage)
: null}
{contentType === 'video' && contentPosition !== 'background'
? videoBlock(illustrationVideo)
: null}
<div className='flex items-center justify-center flex-col space-y-4 w-full lg:w-full'>
<CardBox className='w-full md:w-3/5 lg:w-2/3'>
<CardBoxComponentTitle title="Welcome to your App Draft app!"/>
<div className="space-y-3">
<p className='text-center '>This is a React.js/Node.js app generated by the <a className={`${textColor}`} href="https://flatlogic.com/generator">Flatlogic Web App Generator</a></p>
<p className='text-center '>For guides and documentation please check
your local README.md and the <a className={`${textColor}`} href="https://flatlogic.com/documentation">Flatlogic documentation</a></p>
{/* Navigation */}
<nav className={`fixed top-0 w-full z-50 transition-all duration-300 border-b ${darkMode ? 'bg-slate-900/80 border-slate-700' : 'bg-white/80 border-slate-200'} backdrop-blur-md`}>
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
<div className="flex justify-between h-16 items-center">
<div className="flex items-center space-x-2">
<BaseIcon path={icon.mdiShieldCheck} size={32} className="text-indigo-600" />
<span className="text-xl font-bold tracking-tight">SecureGuard</span>
</div>
<BaseButtons>
<BaseButton
href='/login'
label='Login'
color='info'
className='w-full'
/>
</BaseButtons>
</CardBox>
<div className="hidden md:flex space-x-8 items-center">
<a href="#features" className="hover:text-indigo-600 transition-colors">Features</a>
<a href="#download" className="hover:text-indigo-600 transition-colors">Download</a>
{currentUser ? (
<BaseButton href="/dashboard" label="Dashboard" color="indigo" roundedFull />
) : (
<div className="space-x-4">
<Link href="/login" className="hover:text-indigo-600 transition-colors">Login</Link>
<BaseButton href="/login" label="Get Started" color="indigo" roundedFull />
</div>
)}
</div>
</div>
</div>
</div>
</SectionFullScreen>
<div className='bg-black text-white flex flex-col text-center justify-center md:flex-row'>
<p className='py-6 text-sm'>© 2026 <span>{title}</span>. All rights reserved</p>
<Link className='py-6 ml-4 text-sm' href='/privacy-policy/'>
Privacy Policy
</Link>
</div>
</nav>
{/* Hero Section */}
<section className="pt-32 pb-20 px-4">
<div className="max-w-7xl mx-auto text-center">
<div className="inline-flex items-center space-x-2 bg-indigo-100 dark:bg-indigo-900/30 text-indigo-700 dark:text-indigo-300 px-4 py-2 rounded-full mb-8 text-sm font-medium">
<BaseIcon path={icon.mdiCellphoneLock} size={16} />
<span>Now with advanced Android protection</span>
</div>
<h1 className="text-5xl md:text-7xl font-extrabold mb-6 tracking-tight">
One security suite for <span className="text-indigo-600">all your devices</span>.
</h1>
<p className="text-xl text-slate-600 dark:text-slate-400 max-w-3xl mx-auto mb-10">
SecureGuard keeps your PC and phone protected with a unified dashboard. Connect, scan, and secure your digital life with one click.
</p>
<div className="flex flex-col sm:flex-row justify-center space-y-4 sm:space-y-0 sm:space-x-4 mb-16">
<BaseButton
label="Download for PC"
icon={icon.mdiMonitor}
color="indigo"
className="px-8 py-4 text-lg"
/>
<BaseButton
label="Download for Android"
icon={icon.mdiAndroid}
color="whiteDark"
className="px-8 py-4 text-lg border-2 border-slate-200 dark:border-slate-700"
/>
</div>
{/* Logged-in Device Quick View */}
{currentUser && (
<div className="max-w-4xl mx-auto animate-fade-in">
<CardBox className="text-left border-indigo-500/50 shadow-xl shadow-indigo-500/10">
<div className="flex flex-col md:flex-row md:items-center justify-between mb-6 space-y-4 md:space-y-0">
<div>
<h2 className="text-2xl font-bold">Your Connected Devices</h2>
<p className="text-slate-500">Managing {devices?.length || 0} active devices</p>
</div>
<BaseButton
href="/devices/devices-list"
label="Manage All Devices"
color="indigo"
outline
small
/>
</div>
{devicesLoading ? (
<div className="flex justify-center py-8">
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-indigo-600"></div>
</div>
) : devices && devices.length > 0 ? (
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{devices.slice(0, 3).map((device: any) => (
<div key={device.id} className="p-4 border rounded-xl bg-slate-50 dark:bg-slate-800/50 border-slate-200 dark:border-slate-700">
<div className="flex items-center space-x-3 mb-2">
<BaseIcon
path={device.platform === 'android' ? icon.mdiAndroid : icon.mdiMonitor}
size={24}
className={device.is_connected ? 'text-emerald-500' : 'text-slate-400'}
/>
<span className="font-semibold truncate">{device.name}</span>
</div>
<div className="flex justify-between items-center text-xs">
<span className={`${device.is_connected ? 'text-emerald-500 bg-emerald-100 dark:bg-emerald-900/30' : 'text-slate-400 bg-slate-100 dark:bg-slate-700'} px-2 py-1 rounded-full`}>
{device.is_connected ? 'Connected' : 'Offline'}
</span>
<span className="text-slate-500">Ver: {device.installed_version || '1.0.0'}</span>
</div>
</div>
))}
</div>
) : (
<div className="text-center py-8 bg-slate-50 dark:bg-slate-800/30 rounded-xl border-2 border-dashed border-slate-200 dark:border-slate-700">
<BaseIcon path={icon.mdiPlusCircleOutline} size={48} className="text-slate-300 mb-2" />
<p className="text-slate-500">No devices connected yet.</p>
<BaseButton href="/devices/devices-list" label="Connect first device" color="indigo" outline className="mt-4" />
</div>
)}
</CardBox>
</div>
)}
</div>
</section>
{/* Feature Grid */}
<section id="features" className={`py-20 ${darkMode ? 'bg-slate-800/50' : 'bg-white'}`}>
<div className="max-w-7xl mx-auto px-4">
<div className="text-center mb-16">
<h2 className="text-3xl md:text-4xl font-bold mb-4">Complete protection, everywhere.</h2>
<p className="text-slate-500 max-w-2xl mx-auto text-lg">
SecureGuard provides advanced security features tailored for both desktop and mobile environments.
</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-8">
{features.map((feature, index) => (
<div key={index} className={`p-8 rounded-2xl border transition-all duration-300 hover:shadow-lg ${darkMode ? 'bg-slate-900 border-slate-800' : 'bg-slate-50 border-slate-100'}`}>
<div className={`${feature.color} mb-6 p-3 bg-white dark:bg-slate-800 rounded-xl inline-block shadow-sm`}>
<BaseIcon path={feature.icon} size={32} />
</div>
<h3 className="text-xl font-bold mb-3">{feature.title}</h3>
<p className="text-slate-500 leading-relaxed">
{feature.description}
</p>
</div>
))}
</div>
</div>
</section>
{/* Cross-Platform Tabs */}
<section id="download" className="py-20 px-4">
<div className="max-w-5xl mx-auto bg-indigo-600 rounded-3xl p-8 md:p-16 text-white overflow-hidden relative shadow-2xl shadow-indigo-600/20">
<div className="relative z-10 grid grid-cols-1 lg:grid-cols-2 gap-12 items-center">
<div>
<h2 className="text-4xl font-bold mb-6 tracking-tight">Protect both PC and Android devices.</h2>
<p className="text-indigo-100 text-lg mb-8">
Install SecureGuard on your computer and mobile phone to enable cross-device security monitoring and remote management.
</p>
<div className="space-y-4">
<div className="flex items-center space-x-4 bg-white/10 p-4 rounded-2xl">
<BaseIcon path={icon.mdiCheckCircle} className="text-indigo-200" />
<span>Real-time malware scanning</span>
</div>
<div className="flex items-center space-x-4 bg-white/10 p-4 rounded-2xl">
<BaseIcon path={icon.mdiCheckCircle} className="text-indigo-200" />
<span>Remote device lock and wipe</span>
</div>
<div className="flex items-center space-x-4 bg-white/10 p-4 rounded-2xl">
<BaseIcon path={icon.mdiCheckCircle} className="text-indigo-200" />
<span>Cross-platform threat alerts</span>
</div>
</div>
<div className="mt-10 flex flex-wrap gap-4">
<BaseButton label="Get it on Windows" color="whiteDark" className="text-indigo-600 font-bold" />
<BaseButton label="Get it on Play Store" color="whiteDark" className="text-indigo-600 font-bold" />
</div>
</div>
<div className="relative">
<div className="bg-white/10 backdrop-blur-xl rounded-2xl p-6 border border-white/20 transform rotate-3 scale-105 hidden lg:block">
<div className="flex justify-between items-center mb-4 border-b border-white/10 pb-4">
<div className="flex items-center space-x-2">
<div className="w-3 h-3 rounded-full bg-red-400"></div>
<div className="w-3 h-3 rounded-full bg-yellow-400"></div>
<div className="w-3 h-3 rounded-full bg-green-400"></div>
</div>
<span className="text-xs text-white/60">SecureGuard - Desktop v2.4</span>
</div>
<div className="space-y-4">
<div className="h-4 w-3/4 bg-white/20 rounded"></div>
<div className="h-32 bg-white/10 rounded-xl flex items-center justify-center">
<BaseIcon path={icon.mdiShieldCheck} size={64} className="text-indigo-300" />
</div>
<div className="h-4 w-1/2 bg-white/20 rounded"></div>
<div className="h-4 w-full bg-white/20 rounded"></div>
</div>
</div>
<div className="absolute -bottom-10 -right-10 w-48 bg-slate-900 rounded-3xl p-4 border-8 border-slate-800 shadow-2xl hidden lg:block transform -rotate-6">
<div className="h-full w-full bg-slate-800 rounded-2xl overflow-hidden p-4 flex flex-col items-center">
<BaseIcon path={icon.mdiShieldAccount} size={48} className="text-emerald-500 mb-4" />
<div className="h-2 w-full bg-white/10 rounded mb-2"></div>
<div className="h-2 w-3/4 bg-white/10 rounded mb-8"></div>
<div className="w-full h-10 bg-indigo-600 rounded-lg"></div>
</div>
</div>
</div>
</div>
</div>
</section>
{/* Footer */}
<footer className={`py-12 border-t ${darkMode ? 'bg-slate-900 border-slate-800' : 'bg-white border-slate-200'}`}>
<div className="max-w-7xl mx-auto px-4 grid grid-cols-1 md:grid-cols-4 gap-12">
<div className="col-span-1 md:col-span-1">
<div className="flex items-center space-x-2 mb-6">
<BaseIcon path={icon.mdiShieldCheck} size={24} className="text-indigo-600" />
<span className="text-lg font-bold tracking-tight">SecureGuard</span>
</div>
<p className="text-slate-500 text-sm leading-relaxed">
Providing enterprise-grade security for individuals and families across all digital touchpoints.
</p>
</div>
<div>
<h4 className="font-bold mb-4">Product</h4>
<ul className="space-y-2 text-sm text-slate-500">
<li><a href="#" className="hover:text-indigo-600">Features</a></li>
<li><a href="#" className="hover:text-indigo-600">Security</a></li>
<li><a href="#" className="hover:text-indigo-600">Download</a></li>
<li><a href="#" className="hover:text-indigo-600">Updates</a></li>
</ul>
</div>
<div>
<h4 className="font-bold mb-4">Company</h4>
<ul className="space-y-2 text-sm text-slate-500">
<li><a href="#" className="hover:text-indigo-600">About</a></li>
<li><a href="#" className="hover:text-indigo-600">Contact</a></li>
<li><a href="#" className="hover:text-indigo-600">Privacy</a></li>
<li><a href="#" className="hover:text-indigo-600">Terms</a></li>
</ul>
</div>
<div>
<h4 className="font-bold mb-4">Subscribe</h4>
<p className="text-slate-500 text-sm mb-4">Get the latest security tips and news.</p>
<div className="flex">
<input type="email" placeholder="Email address" className={`p-2 rounded-l-lg border-y border-l w-full text-sm outline-none focus:ring-1 focus:ring-indigo-500 ${darkMode ? 'bg-slate-800 border-slate-700' : 'bg-slate-50 border-slate-200'}`} />
<button className="bg-indigo-600 text-white px-4 rounded-r-lg text-sm font-bold">Join</button>
</div>
</div>
</div>
<div className="max-w-7xl mx-auto px-4 mt-12 pt-8 border-t border-slate-100 dark:border-slate-800 text-center text-slate-400 text-xs">
© 2026 SecureGuard. All rights reserved. Built for PC and Android.
</div>
</footer>
</div>
);
}
Starter.getLayout = function getLayout(page: ReactElement) {
LandingPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};
};