38838-vm/frontend/src/pages/web_pages/startup-details.tsx
Flatlogic Bot 8c8258f7b8 v2
2026-02-28 13:06:56 +00:00

250 lines
14 KiB
TypeScript
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React, { useEffect, useState } from 'react';
import type { ReactElement } from 'react';
import Head from 'next/head';
import { useRouter } from 'next/router';
import axios from 'axios';
import LayoutGuest from '../../layouts/Guest';
import SectionMain from '../../components/SectionMain';
import CardBox from '../../components/CardBox';
import UserAvatar from '../../components/UserAvatar';
import BaseIcon from '../../components/BaseIcon';
import {
mdiRocketLaunch,
mdiMapMarkerOutline,
mdiTagOutline,
mdiWeb,
mdiEmailOutline,
mdiGithub,
mdiTrendingUp,
mdiAccountGroup,
mdiCurrencyUsd,
mdiCalendarRange
} from '@mdi/js';
import BaseButton from '../../components/BaseButton';
import BaseButtons from '../../components/BaseButtons';
import { getPageTitle } from '../../config';
export default function StartupDetailsPage() {
const router = useRouter();
const { id } = router.query;
const [startup, setStartup] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
if (id && typeof id === 'string') {
const fetchStartup = async () => {
try {
setLoading(true);
const response = await axios.get(`/startups/${id}`);
setStartup(response.data);
} catch (err) {
console.error('Failed to fetch startup:', err);
setError(err);
} finally {
setLoading(false);
}
};
fetchStartup();
} else if (router.isReady && !id) {
setLoading(false);
}
}, [id, router.isReady]);
if (loading) {
return (
<SectionMain>
<div className="flex justify-center items-center min-h-64">
<p className="text-gray-500 text-lg">Loading startup profile...</p>
</div>
</SectionMain>
);
}
if (error || (!startup && !loading)) {
return (
<SectionMain>
<div className="text-center py-20 bg-white rounded-xl border">
<h2 className="text-2xl font-bold text-gray-800 mb-2">Startup Not Found</h2>
<p className="text-gray-500 mb-6">The startup profile you&apos;re looking for doesn&apos;t exist or is no longer available.</p>
<BaseButton label="Back to Marketplace" href="/" color="info" />
</div>
</SectionMain>
);
}
return (
<div className="bg-gray-50 min-h-screen pb-20">
<Head>
<title>{getPageTitle(startup.name || 'Startup Details')}</title>
</Head>
{/* Header / Hero */}
<div className="bg-white border-b py-12">
<div className="container mx-auto px-6">
<div className="flex flex-col md:flex-row items-center md:items-start text-center md:text-left">
<UserAvatar
username={startup.name}
className="w-32 h-32 md:mr-10 mb-6 md:mb-0"
/>
<div className="flex-grow">
<div className="flex flex-col md:flex-row md:items-center mb-2">
<h1 className="text-4xl font-bold text-gray-900 mr-4">{startup.name}</h1>
<span className="inline-block px-3 py-1 bg-blue-100 text-blue-800 rounded-full text-sm font-semibold mt-2 md:mt-0 uppercase">
{startup.stage || 'IDEA'}
</span>
</div>
<p className="text-xl text-gray-600 mb-6 font-medium italic">
{startup.tagline || 'Innovation in the making.'}
</p>
<div className="flex flex-wrap justify-center md:justify-start gap-4 text-gray-500">
<div className="flex items-center">
<BaseIcon path={mdiMapMarkerOutline} className="mr-1" />
{startup.location || 'Remote'}
</div>
<div className="flex items-center">
<BaseIcon path={mdiTagOutline} className="mr-1" />
{startup.industry || 'Tech'}
</div>
<div className="flex items-center">
<BaseIcon path={mdiCalendarRange} className="mr-1" />
Founded {startup.founded_at ? new Date(startup.founded_at).getFullYear() : 'N/A'}
</div>
</div>
</div>
<div className="mt-8 md:mt-0 flex flex-col space-y-3 w-full md:w-auto">
<BaseButton label="Contact Founder" color="info" href="/login" className="w-full md:w-48" />
<BaseButton label="Watch Demo" outline color="info" href={startup.demo_url || '/login'} className="w-full md:w-48" />
</div>
</div>
</div>
</div>
<SectionMain>
<div className="grid grid-cols-1 lg:grid-cols-3 gap-8">
{/* Main Content */}
<div className="lg:col-span-2 space-y-8">
<CardBox>
<h2 className="text-2xl font-bold mb-4">About</h2>
<p className="text-gray-700 leading-relaxed whitespace-pre-wrap">
{startup.description || 'No detailed description available.'}
</p>
</CardBox>
<CardBox>
<h2 className="text-2xl font-bold mb-6">Business Metrics</h2>
<div className="grid grid-cols-1 sm:grid-cols-2 gap-6">
<div className="flex items-start p-4 bg-gray-50 rounded-xl border border-gray-100">
<div className="p-3 bg-blue-100 rounded-lg mr-4">
<BaseIcon path={mdiTrendingUp} className="text-blue-600" />
</div>
<div>
<p className="text-sm text-gray-500 uppercase font-bold tracking-wider">Revenue</p>
<p className="text-xl font-bold">${parseFloat(startup.monthly_revenue || 0).toLocaleString()}/mo</p>
</div>
</div>
<div className="flex items-start p-4 bg-gray-50 rounded-xl border border-gray-100">
<div className="p-3 bg-green-100 rounded-lg mr-4">
<BaseIcon path={mdiAccountGroup} className="text-green-600" />
</div>
<div>
<p className="text-sm text-gray-500 uppercase font-bold tracking-wider">Team Size</p>
<p className="text-xl font-bold">{startup.team_size || '1-10'} members</p>
</div>
</div>
<div className="flex items-start p-4 bg-gray-50 rounded-xl border border-gray-100">
<div className="p-3 bg-purple-100 rounded-lg mr-4">
<BaseIcon path={mdiCurrencyUsd} className="text-purple-600" />
</div>
<div>
<p className="text-sm text-gray-500 uppercase font-bold tracking-wider">Funding Stage</p>
<p className="text-xl font-bold uppercase">{startup.funding_stage || 'Bootstrapped'}</p>
</div>
</div>
<div className="flex items-start p-4 bg-gray-50 rounded-xl border border-gray-100">
<div className="p-3 bg-orange-100 rounded-lg mr-4">
<BaseIcon path={mdiRocketLaunch} className="text-orange-600" />
</div>
<div>
<p className="text-sm text-gray-500 uppercase font-bold tracking-wider">Business Model</p>
<p className="text-xl font-bold uppercase">{startup.business_model || 'SaaS'}</p>
</div>
</div>
</div>
</CardBox>
</div>
{/* Sidebar */}
<div className="space-y-6">
<CardBox>
<h2 className="text-xl font-bold mb-4">Quick Links</h2>
<div className="space-y-4">
{startup.website_url && (
<a href={startup.website_url} target="_blank" rel="noreferrer" className="flex items-center p-3 hover:bg-gray-50 rounded-xl border transition group">
<div className="p-2 bg-gray-100 rounded-lg mr-3 group-hover:bg-blue-50 group-hover:text-blue-600 transition">
<BaseIcon path={mdiWeb} />
</div>
<span className="font-medium">Official Website</span>
</a>
)}
{startup.contact_email && (
<a href={`mailto:${startup.contact_email}`} className="flex items-center p-3 hover:bg-gray-50 rounded-xl border transition group">
<div className="p-2 bg-gray-100 rounded-lg mr-3 group-hover:bg-blue-50 group-hover:text-blue-600 transition">
<BaseIcon path={mdiEmailOutline} />
</div>
<span className="font-medium">Email Contact</span>
</a>
)}
{startup.github_url && (
<a href={startup.github_url} target="_blank" rel="noreferrer" className="flex items-center p-3 hover:bg-gray-50 rounded-xl border transition group">
<div className="p-2 bg-gray-100 rounded-lg mr-3 group-hover:bg-blue-50 group-hover:text-blue-600 transition">
<BaseIcon path={mdiGithub} />
</div>
<span className="font-medium">GitHub Repository</span>
</a>
)}
</div>
</CardBox>
<CardBox className="bg-blue-50 border-blue-100">
<h2 className="text-xl font-bold mb-4 text-blue-900">Seeking</h2>
<div className="space-y-3">
{startup.is_seeking_investment && (
<div className="flex items-center p-2 px-3 bg-white border border-blue-200 rounded-lg text-blue-700 font-bold">
<span className="mr-2">💰</span> Investment
</div>
)}
{startup.is_seeking_partners && (
<div className="flex items-center p-2 px-3 bg-white border border-blue-200 rounded-lg text-blue-700 font-bold">
<span className="mr-2">🤝</span> Partners
</div>
)}
{startup.is_hiring && (
<div className="flex items-center p-2 px-3 bg-white border border-blue-200 rounded-lg text-blue-700 font-bold">
<span className="mr-2">👨💻</span> Hiring
</div>
)}
{!startup.is_seeking_investment && !startup.is_seeking_partners && !startup.is_hiring && (
<p className="text-sm text-gray-500 italic">No specific needs listed at this time.</p>
)}
</div>
</CardBox>
<div className="p-6 bg-white rounded-xl border text-center">
<h3 className="font-bold mb-2">Interested in {startup.name}?</h3>
<p className="text-sm text-gray-500 mb-4">Create an account to save this startup to your favorites and get notified about updates.</p>
<BaseButton label="Join for Free" color="info" href="/login" className="w-full" />
</div>
</div>
</div>
</SectionMain>
</div>
);
}
StartupDetailsPage.getLayout = function getLayout(page: ReactElement) {
return <LayoutGuest>{page}</LayoutGuest>;
};