250 lines
14 KiB
TypeScript
250 lines
14 KiB
TypeScript
|
||
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're looking for doesn'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>;
|
||
};
|