Initial commit from gitea_uploader script
This commit is contained in:
parent
d8da7beb52
commit
a85fa0d211
3
.npmrc
Normal file
3
.npmrc
Normal file
@ -0,0 +1,3 @@
|
||||
# npm configuration
|
||||
registry=https://registry.npmjs.org/
|
||||
save-exact=true
|
||||
17
Dockerfile
17
Dockerfile
@ -35,9 +35,9 @@ ARG USERNAME=node
|
||||
ARG USER_UID=1000
|
||||
ARG USER_GID=$USER_UID
|
||||
|
||||
# Create the user
|
||||
RUN groupadd --gid $USER_GID $USERNAME \
|
||||
&& useradd --uid $USER_UID --gid $USER_GID -m $USERNAME \
|
||||
# Create the user (skip if already exists)
|
||||
RUN (groupadd --gid $USER_GID $USERNAME || true) \
|
||||
&& (useradd --uid $USER_UID --gid $USER_GID -m $USERNAME || true) \
|
||||
&& apt-get update \
|
||||
&& apt-get install -y sudo \
|
||||
&& echo $USERNAME ALL=\(root\) NOPASSWD:ALL > /etc/sudoers.d/$USERNAME \
|
||||
@ -57,13 +57,16 @@ COPY requirements.txt ./
|
||||
RUN --mount=type=cache,target=/root/.npm \
|
||||
npm ci
|
||||
|
||||
# Install Python dependencies with cache
|
||||
# Install Python dependencies with cache (skip if no real dependencies)
|
||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||
pip3 install -r requirements.txt
|
||||
pip3 install --break-system-packages -r requirements.txt || echo "No Python dependencies to install"
|
||||
|
||||
# Switch to non-root user
|
||||
USER $USERNAME
|
||||
|
||||
# Set the default command for development
|
||||
CMD ["npm", "run", "dev"]
|
||||
|
||||
# Production stage
|
||||
FROM base AS prod
|
||||
|
||||
@ -76,9 +79,9 @@ COPY requirements.txt ./
|
||||
RUN --mount=type=cache,target=/root/.npm \
|
||||
npm ci --only=production
|
||||
|
||||
# Install Python production dependencies
|
||||
# Install Python production dependencies (skip if no real dependencies)
|
||||
RUN --mount=type=cache,target=/root/.cache/pip \
|
||||
pip3 install -r requirements.txt
|
||||
pip3 install --break-system-packages -r requirements.txt || echo "No Python dependencies to install"
|
||||
|
||||
# Copy application code
|
||||
COPY . .
|
||||
|
||||
232
README.md
232
README.md
@ -1,36 +1,226 @@
|
||||
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).
|
||||
# 🦉 CCFW Wildlife Livestream Platform
|
||||
|
||||
## Getting Started
|
||||
A modern, professional web application dedicated to **Cape Coral Friends of Wildlife (CCFW)** that provides real-time wildlife streaming with a focus on Florida's burrowing owls and conservation efforts. Built with cutting-edge web technologies and designed for maximum accessibility and user experience.
|
||||
|
||||
First, run the development server:
|
||||
[](https://nextjs.org/)
|
||||
[](https://www.typescriptlang.org/)
|
||||
[](https://tailwindcss.com/)
|
||||
[](https://www.docker.com/)
|
||||
|
||||
## 🌟 Features
|
||||
|
||||
### 🎥 **Live Wildlife Streaming**
|
||||
- **Multiple HD livestream channels** focusing on Florida's native wildlife
|
||||
- **Real-time status indicators** showing live/offline status
|
||||
- **Professional streaming interface** with viewer counts and quality badges
|
||||
- **Burrowing owl focus** - dedicated streams from Cape Coral's protected habitats
|
||||
|
||||
### 🦉 **Burrowing Owl Conservation**
|
||||
- **Educational content** about burrowing owl behavior and habitats
|
||||
- **Conservation information** highlighting CCFW's 2,500+ burrow maintenance program
|
||||
- **Interactive maps** showing owl locations and protected areas
|
||||
- **Volunteer opportunities** and ways to get involved
|
||||
|
||||
### 💝 **Support & Donations**
|
||||
- **Integrated donation system** with multiple payment options
|
||||
- **Membership management** for annual and multi-year memberships
|
||||
- **Impact tracking** showing volunteer hours and conservation achievements
|
||||
- **Tax-deductible donations** supporting Florida wildlife preservation
|
||||
|
||||
### 🎨 **Modern Design & UX**
|
||||
- **Responsive design** that works perfectly on all devices
|
||||
- **Dark mode optimized** with excellent contrast ratios
|
||||
- **Smooth animations** and micro-interactions
|
||||
- **Accessibility compliant** with proper focus states and screen reader support
|
||||
- **Professional branding** using CCFW's official colors and themes
|
||||
|
||||
### 📊 **Interactive Features**
|
||||
- **Real-time statistics** showing viewer counts and stream activity
|
||||
- **Interactive wildlife facts** with educational content
|
||||
- **Social media integration** with direct links to CCFW's platforms
|
||||
- **Event calendar integration** for upcoming livestreams and events
|
||||
|
||||
## 🛠️ Tech Stack
|
||||
|
||||
### **Frontend**
|
||||
- **Next.js 13+** with App Router for optimal performance
|
||||
- **TypeScript** for type safety and better developer experience
|
||||
- **Tailwind CSS** for utility-first styling
|
||||
- **shadcn/ui** component library for consistent, accessible UI components
|
||||
- **React Hook Form** for form management
|
||||
|
||||
### **Development & Deployment**
|
||||
- **Docker** containerization for consistent development environments
|
||||
- **ESLint & Prettier** for code quality and formatting
|
||||
- **Git** for version control with comprehensive commit history
|
||||
|
||||
### **Performance & SEO**
|
||||
- **Server-Side Rendering (SSR)** for fast initial page loads
|
||||
- **Image optimization** with Next.js Image component
|
||||
- **Static generation** for improved performance
|
||||
- **SEO optimized** with proper meta tags and structured data
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### **Prerequisites**
|
||||
- Node.js 18+ or Docker
|
||||
- Git for version control
|
||||
|
||||
### **Installation**
|
||||
|
||||
#### **Option 1: Using Docker (Recommended)**
|
||||
```bash
|
||||
npm run dev
|
||||
# or
|
||||
yarn dev
|
||||
# or
|
||||
pnpm dev
|
||||
# or
|
||||
bun dev
|
||||
# Clone the repository
|
||||
git clone https://github.com/your-username/ccfw-livestream.git
|
||||
cd ccfw-livestream
|
||||
|
||||
# Start with Docker Compose
|
||||
docker-compose up -d
|
||||
|
||||
# The application will be available at http://localhost:3000
|
||||
```
|
||||
|
||||
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
|
||||
#### **Option 2: Local Development**
|
||||
```bash
|
||||
# Clone the repository
|
||||
git clone https://github.com/your-username/ccfw-livestream.git
|
||||
cd ccfw-livestream
|
||||
|
||||
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
|
||||
# Install dependencies
|
||||
npm install
|
||||
|
||||
This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.
|
||||
# Start development server
|
||||
npm run dev
|
||||
|
||||
## Learn More
|
||||
# Open http://localhost:3000 in your browser
|
||||
```
|
||||
|
||||
To learn more about Next.js, take a look at the following resources:
|
||||
### **Environment Variables**
|
||||
Create a `.env.local` file in the root directory:
|
||||
```env
|
||||
NEXT_PUBLIC_SITE_URL=http://localhost:3000
|
||||
# Add other environment variables as needed
|
||||
```
|
||||
|
||||
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
|
||||
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
|
||||
## 📸 Screenshots
|
||||
|
||||
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!
|
||||
### **Main Landing Page**
|
||||

|
||||
*Professional landing page with featured livestreams and conservation information*
|
||||
|
||||
## Deploy on Vercel
|
||||
### **Live Streaming Interface**
|
||||

|
||||
*HD streaming interface with real-time viewer counts and professional controls*
|
||||
|
||||
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
|
||||
### **Burrowing Owl Information**
|
||||

|
||||
*Educational content about burrowing owls with conservation facts and habitat information*
|
||||
|
||||
Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
|
||||
## 🏗️ Project Structure
|
||||
|
||||
```
|
||||
ccfw-livestream/
|
||||
├── app/ # Next.js app directory
|
||||
│ ├── components/ # Reusable React components
|
||||
│ │ ├── ui/ # shadcn/ui components
|
||||
│ │ ├── LiveStream.tsx # Main streaming component
|
||||
│ │ ├── OwlInfo.tsx # Wildlife information
|
||||
│ │ └── DonationPanel.tsx # Donation interface
|
||||
│ ├── livestream/ # Dynamic livestream pages
|
||||
│ │ └── [id]/ # Individual stream pages
|
||||
│ ├── globals.css # Global styles
|
||||
│ ├── layout.tsx # Root layout
|
||||
│ └── page.tsx # Main landing page
|
||||
├── components/ # Shared UI components
|
||||
├── public/ # Static assets
|
||||
├── images/ # Screenshots and documentation
|
||||
├── Dockerfile # Container configuration
|
||||
├── docker-compose.yml # Docker orchestration
|
||||
└── README.md # This file
|
||||
```
|
||||
|
||||
## 🎯 Key Components
|
||||
|
||||
### **LiveStream Component**
|
||||
- **HD video player** with professional controls
|
||||
- **Real-time status** indicators (Live/Offline)
|
||||
- **Viewer statistics** and engagement metrics
|
||||
- **Accessibility features** for screen readers
|
||||
- **Responsive design** for all screen sizes
|
||||
|
||||
### **OwlInfo Component**
|
||||
- **Interactive tabs** for different information categories
|
||||
- **Educational content** about burrowing owls
|
||||
- **Conservation facts** and habitat information
|
||||
- **Visual elements** with proper contrast ratios
|
||||
|
||||
### **DonationPanel Component**
|
||||
- **Multiple donation amounts** with quick selection
|
||||
- **Form validation** and error handling
|
||||
- **Secure payment processing** integration ready
|
||||
- **Impact visualization** showing conservation benefits
|
||||
|
||||
## 🌱 Conservation Impact
|
||||
|
||||
This platform serves as a vital tool for **Cape Coral Friends of Wildlife (CCFW)** to:
|
||||
|
||||
- **Educate the public** about burrowing owl conservation
|
||||
- **Showcase live conservation efforts** in real-time
|
||||
- **Fundraise for habitat protection** through donations
|
||||
- **Recruit volunteers** for burrow maintenance programs
|
||||
- **Track and display conservation impact** metrics
|
||||
|
||||
### **CCFW Mission Support**
|
||||
- **2,500+ burrows** maintained annually
|
||||
- **500+ active members** and volunteers
|
||||
- **Educational outreach** to local communities
|
||||
- **Habitat preservation** in urban environments
|
||||
- **Research and monitoring** of protected species
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
We welcome contributions to improve the CCFW Wildlife Livestream Platform!
|
||||
|
||||
### **Development Guidelines**
|
||||
1. **Fork** the repository
|
||||
2. **Create** a feature branch (`git checkout -b feature/amazing-feature`)
|
||||
3. **Commit** your changes (`git commit -m 'Add amazing feature'`)
|
||||
4. **Push** to the branch (`git push origin feature/amazing-feature`)
|
||||
5. **Open** a Pull Request
|
||||
|
||||
### **Code Standards**
|
||||
- Use **TypeScript** for all new code
|
||||
- Follow **ESLint** and **Prettier** configurations
|
||||
- Maintain **accessibility standards** (WCAG 2.1)
|
||||
- Write **comprehensive tests** for new features
|
||||
- Document **components and functions** with JSDoc
|
||||
|
||||
## 📄 License
|
||||
|
||||
This project is licensed under the **MIT License** - see the [LICENSE](LICENSE) file for details.
|
||||
|
||||
## 🙏 Acknowledgments
|
||||
|
||||
- **Cape Coral Friends of Wildlife** for their dedication to wildlife conservation
|
||||
- **Florida wildlife enthusiasts** and conservation volunteers
|
||||
- **Open source community** for the amazing tools and libraries
|
||||
- **Burrowing owl researchers** and habitat experts
|
||||
|
||||
## 📞 Contact
|
||||
|
||||
**Cape Coral Friends of Wildlife**
|
||||
- Website: [ccfriendsofwildlife.org](https://ccfriendsofwildlife.org)
|
||||
- Phone: (239) 980-2593
|
||||
- Email: info@ccfriendsofwildlife.org
|
||||
|
||||
**Project Repository**
|
||||
- GitHub: [github.com/your-username/ccfw-livestream](https://github.com/your-username/ccfw-livestream)
|
||||
- Issues: [Report bugs and request features](https://github.com/your-username/ccfw-livestream/issues)
|
||||
|
||||
## 🌟 Star this Repository
|
||||
|
||||
If you find this project helpful for wildlife conservation and education, please consider giving it a ⭐ on GitHub!
|
||||
|
||||
---
|
||||
|
||||
*Built with ❤️ for Florida's wildlife and conservation efforts*
|
||||
|
||||
@ -1,6 +1,8 @@
|
||||
import React from 'react';
|
||||
"use client";
|
||||
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import React, { useState } from 'react';
|
||||
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
|
||||
@ -9,22 +11,118 @@ interface DonationPanelProps {
|
||||
}
|
||||
|
||||
const DonationPanel: React.FC<DonationPanelProps> = ({ id }) => {
|
||||
const [amount, setAmount] = useState<number>(25);
|
||||
const [donated, setDonated] = useState<boolean>(false);
|
||||
const [donationInProgress, setDonationInProgress] = useState<boolean>(false);
|
||||
|
||||
const handleAmountChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||
const value = parseInt(e.target.value);
|
||||
if (!isNaN(value)) {
|
||||
setAmount(value);
|
||||
} else {
|
||||
setAmount(0);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDonate = () => {
|
||||
if (amount > 0) {
|
||||
setDonationInProgress(true);
|
||||
// Simulate API call
|
||||
setTimeout(() => {
|
||||
setDonated(true);
|
||||
setDonationInProgress(false);
|
||||
}, 1500);
|
||||
}
|
||||
};
|
||||
|
||||
const predefinedAmounts = [10, 25, 50, 100];
|
||||
|
||||
return (
|
||||
<Card className="bg-black/30 border-accent/50 backdrop-blur-sm">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-accent neon-glow">Support Wildlife</CardTitle>
|
||||
<Card className="border-ccfw-teal/30 bg-gradient-to-b from-ccfw-beige/20 to-ccfw-beige/5 backdrop-blur-sm">
|
||||
<CardHeader className="border-b border-ccfw-teal/20 bg-ccfw-beige/10">
|
||||
<CardTitle className="text-ccfw-teal">Support Wildlife</CardTitle>
|
||||
<CardDescription className="text-ccfw-maroon font-medium">
|
||||
Help protect the wildlife featured in Livestream {id}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CardContent className="pt-4">
|
||||
{!donated ? (
|
||||
<div className="space-y-4">
|
||||
<p className="text-foreground/80">Your donation helps protect and preserve the habitats of these amazing creatures.</p>
|
||||
<div className="flex items-center justify-center p-4 bg-accent/10 rounded-md">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-12 w-12 text-accent" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M12 8c-1.657 0-3 .895-3 2s1.343 2 3 2 3 .895 3 2-1.343 2-3 2m0-8c1.11 0 2.08 .402 2.599 1M12 8V7m0 1v8m0 0v1m0-1c-1.11 0-2.08-.402-2.599-1M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
<p className="text-ccfw-maroon font-medium">Your donation helps protect and preserve the habitats of these amazing creatures.</p>
|
||||
|
||||
<div className="grid grid-cols-4 gap-2 my-4">
|
||||
{predefinedAmounts.map((presetAmount) => (
|
||||
<Button
|
||||
key={presetAmount}
|
||||
variant={amount === presetAmount ? "default" : "outline"}
|
||||
className={amount === presetAmount ? "bg-ccfw-teal text-white" : "border-ccfw-teal/30 text-foreground hover:bg-ccfw-teal/10"}
|
||||
onClick={() => setAmount(presetAmount)}
|
||||
>
|
||||
${presetAmount}
|
||||
</Button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="relative">
|
||||
<div className="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
|
||||
<span className="text-ccfw-maroon font-medium">$</span>
|
||||
</div>
|
||||
<Input
|
||||
type="number"
|
||||
value={amount}
|
||||
onChange={handleAmountChange}
|
||||
className="bg-ccfw-beige/20 border-ccfw-teal/30 text-foreground pl-7"
|
||||
placeholder="Custom amount"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center space-x-2 pt-2">
|
||||
<div className="h-10 w-10 rounded-full bg-ccfw-gold/20 flex items-center justify-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-ccfw-gold" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<Input type="number" placeholder="Amount in USD" className="bg-black/50 border-accent/30 text-foreground" />
|
||||
<Button className="w-full bg-accent text-accent-foreground hover:bg-accent/80">Donate Now</Button>
|
||||
<p className="text-sm text-ccfw-maroon font-medium">100% of donations go directly to CCFW conservation efforts</p>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
onClick={handleDonate}
|
||||
disabled={amount <= 0 || donationInProgress}
|
||||
className="w-full bg-ccfw-teal text-white hover:bg-ccfw-teal/80 relative overflow-hidden"
|
||||
>
|
||||
{donationInProgress ? (
|
||||
<>
|
||||
<span className="opacity-0">Donate Now</span>
|
||||
<span className="absolute inset-0 flex items-center justify-center">
|
||||
<svg className="animate-spin h-5 w-5 text-white" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
|
||||
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4"></circle>
|
||||
<path className="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path>
|
||||
</svg>
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
`Donate $${amount}`
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-4 text-center">
|
||||
<div className="mx-auto w-16 h-16 rounded-full bg-ccfw-gold/20 flex items-center justify-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-8 w-8 text-ccfw-gold" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M5 13l4 4L19 7" />
|
||||
</svg>
|
||||
</div>
|
||||
<h3 className="text-xl font-bold text-ccfw-teal">Thank You!</h3>
|
||||
<p className="text-ccfw-maroon font-medium">Your donation of ${amount} will help protect Florida wildlife.</p>
|
||||
<div className="text-sm text-ccfw-maroon font-medium mt-2">
|
||||
Cape Coral Friends of Wildlife is a 501(c)(3) non-profit organization.
|
||||
All donations are tax-deductible.
|
||||
</div>
|
||||
<Button onClick={() => setDonated(false)} variant="outline" className="border-ccfw-teal/30 text-ccfw-teal mt-4 hover:bg-ccfw-teal/10">
|
||||
Make Another Donation
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
||||
@ -1,3 +1,5 @@
|
||||
"use client";
|
||||
|
||||
import React from 'react';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
|
||||
@ -5,15 +7,183 @@ interface LiveStreamProps {
|
||||
id: string;
|
||||
}
|
||||
|
||||
// Define burrowing owl info based on stream ID
|
||||
const getStreamInfo = (id: string) => {
|
||||
switch (id) {
|
||||
case "1":
|
||||
return {
|
||||
title: "Cape Coral Burrowing Owl",
|
||||
location: "Cape Coral, FL",
|
||||
fact: "The burrowing owl is the official city bird of Cape Coral. These unique owls nest underground and are active during the day."
|
||||
};
|
||||
case "2":
|
||||
return {
|
||||
title: "Burrowing Owl Habitat",
|
||||
location: "Cape Coral, FL",
|
||||
fact: "Burrowing owls prefer open areas with low vegetation and create underground burrows that provide shelter for many wildlife species."
|
||||
};
|
||||
case "3":
|
||||
return {
|
||||
title: "Owl Burrow Monitoring",
|
||||
location: "Cape Coral, FL",
|
||||
fact: "CCFW volunteers maintain over 2,500 burrows throughout Cape Coral to protect these threatened ground-dwelling owls."
|
||||
};
|
||||
default:
|
||||
return {
|
||||
title: `Burrowing Owl Cam ${id}`,
|
||||
location: "Cape Coral, FL",
|
||||
fact: "Burrowing owls are Florida's smallest owl species and are known for their distinctive long legs and daytime activity."
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
// Client-side component for dynamic time to avoid hydration errors
|
||||
const ClientTimeDisplay: React.FC = () => {
|
||||
const [currentTime, setCurrentTime] = React.useState<string>('');
|
||||
|
||||
React.useEffect(() => {
|
||||
setCurrentTime(new Date().toLocaleDateString() + ' • ' + new Date().toLocaleTimeString());
|
||||
}, []);
|
||||
|
||||
return <span className="bg-ccfw-beige/50 py-1 px-2 rounded">{currentTime}</span>;
|
||||
};
|
||||
|
||||
const LiveStream: React.FC<LiveStreamProps> = ({ id }) => {
|
||||
// This would be determined by your backend in a real app
|
||||
const isLive = id !== "3"; // Let's assume stream #3 is offline for testing
|
||||
|
||||
const streamInfo = getStreamInfo(id);
|
||||
// Use a fixed viewer count to avoid hydration errors
|
||||
const viewerCount = isLive ? (id === "1" ? 128 : id === "2" ? 86 : 75) : 0;
|
||||
|
||||
return (
|
||||
<Card className="bg-black/30 border-accent/50 backdrop-blur-sm">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-accent neon-glow">Live Cam {id}</CardTitle>
|
||||
<Card className="border-ccfw-teal/30 bg-gradient-to-b from-ccfw-beige/20 to-ccfw-beige/5 backdrop-blur-sm">
|
||||
<CardHeader className="pb-2 border-b border-ccfw-teal/20">
|
||||
<div className="flex justify-between items-center">
|
||||
<CardTitle className="text-ccfw-teal">{streamInfo.title}</CardTitle>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className={`h-3 w-3 rounded-full ${isLive ? 'bg-ccfw-coral animate-pulse' : 'bg-gray-500'}`}></div>
|
||||
<span className="text-sm font-medium text-ccfw-maroon font-semibold">{isLive ? 'LIVE' : 'OFFLINE'}</span>
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<div className="bg-black aspect-video flex items-center justify-center rounded-md border border-accent/30">
|
||||
<p className="text-accent">Livestream {id} placeholder</p>
|
||||
<CardContent className="pt-4">
|
||||
<div className="bg-black aspect-video flex flex-col items-center justify-center rounded-md border border-ccfw-teal/30 relative overflow-hidden">
|
||||
{isLive ? (
|
||||
<>
|
||||
<div className="absolute inset-0 bg-gradient-to-b from-ccfw-teal/5 to-transparent"></div>
|
||||
|
||||
{/* Overlay for wildlife stream info */}
|
||||
<div className="absolute top-0 left-0 w-full bg-black/50 p-2 flex justify-between items-center">
|
||||
<div className="flex items-center">
|
||||
<div className="h-2 w-2 rounded-full bg-ccfw-coral animate-pulse mr-2"></div>
|
||||
<span className="text-xs text-white">CCFW Wildlife Stream</span>
|
||||
</div>
|
||||
<div className="text-xs text-white bg-ccfw-teal/80 px-2 py-1 rounded">
|
||||
HD
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="z-10 flex flex-col items-center">
|
||||
<div className="bg-black/60 px-4 py-2 rounded-lg border border-ccfw-teal/30">
|
||||
<p className="text-white font-medium">{streamInfo.location} • Cape Coral Friends of Wildlife</p>
|
||||
<p className="text-xs text-white mt-2">HD Video • Live from Florida</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="absolute bottom-4 right-4 bg-black/70 text-white text-xs px-2 py-1 rounded flex items-center">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-3 w-3 mr-1 text-ccfw-coral" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 12a3 3 0 11-6 0 3 3 0 016 0z" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z" />
|
||||
</svg>
|
||||
{viewerCount}
|
||||
</div>
|
||||
|
||||
{/* Stream controls overlay */}
|
||||
<div className="absolute bottom-0 left-0 w-full bg-gradient-to-t from-black to-transparent pt-8 pb-2 px-4">
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex space-x-3">
|
||||
<button className="text-white hover:text-ccfw-coral transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M15.536 8.464a5 5 0 010 7.072m2.828-9.9a9 9 0 010 12.728M5.586 15.536a5 5 0 001.414-7.071m-2.829 9.9a9 9 0 010-12.728" />
|
||||
</svg>
|
||||
</button>
|
||||
<button className="text-white hover:text-ccfw-coral transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M5 3v4M3 5h4M6 17v4m-2-2h4m5-16l2.286 6.857L21 12l-5.714 2.143L13 21l-2.286-6.857L5 12l5.714-2.143L13 3z" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
<div className="text-xs text-white">
|
||||
Powered by CCFW
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
) : (
|
||||
<div className="flex flex-col items-center">
|
||||
<div className="bg-black/60 p-4 rounded-lg border border-ccfw-teal/30">
|
||||
<div className="flex items-center mb-3">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-10 w-10 text-gray-600 mr-3" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M14.752 11.168l-3.197-2.132A1 1 0 0010 9.87v4.263a1 1 0 001.555.832l3.197-2.132a1 1 0 000-1.664z" />
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<div>
|
||||
<p className="text-white font-medium">Stream currently offline</p>
|
||||
<p className="text-xs text-white/80">Will return soon. Check back later.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-xs text-white text-center">
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/events-and-programs/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hover:text-ccfw-coral transition-colors"
|
||||
>
|
||||
View upcoming livestream schedule
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="mt-4 flex justify-between items-center">
|
||||
<div className="text-xs text-ccfw-maroon/70">
|
||||
<ClientTimeDisplay />
|
||||
</div>
|
||||
<div className="flex gap-3">
|
||||
<button className="text-ccfw-teal hover:text-ccfw-coral transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M8.684 13.342C8.886 12.938 9 12.482 9 12c0-.482-.114-.938-.316-1.342m0 2.684a3 3 0 110-2.684m0 2.684l6.632 3.316m-6.632-6l6.632-3.316m0 0a3 3 0 105.367-2.684 3 3 0 00-5.367 2.684zm0 9.316a3 3 0 105.368 2.684 3 3 0 00-5.368-2.684z" />
|
||||
</svg>
|
||||
</button>
|
||||
<button className="text-ccfw-teal hover:text-ccfw-coral transition-colors">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M4.318 6.318a4.5 4.5 0 000 6.364L12 20.364l7.682-7.682a4.5 4.5 0 00-6.364-6.364L12 7.636l-1.318-1.318a4.5 4.5 0 00-6.364 0z" />
|
||||
</svg>
|
||||
</button>
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/events-and-programs/"
|
||||
target="_blank"
|
||||
className="text-ccfw-teal hover:text-ccfw-coral transition-colors"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Wildlife fact */}
|
||||
<div className="mt-3 bg-ccfw-beige/10 p-3 rounded-md border border-ccfw-teal/20">
|
||||
<div className="flex items-start gap-2">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 text-ccfw-gold flex-shrink-0 mt-0.5" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<p className="text-sm text-ccfw-maroon font-medium leading-relaxed">
|
||||
<span className="font-semibold text-ccfw-teal">Wildlife Fact:</span> {streamInfo.fact}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
@ -1,21 +1,179 @@
|
||||
import React from 'react';
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
"use client";
|
||||
|
||||
import React, { useState } from 'react';
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
|
||||
interface OwlInfoProps {
|
||||
id: string;
|
||||
}
|
||||
|
||||
const OwlInfo: React.FC<OwlInfoProps> = ({ id }) => {
|
||||
const [activeTab, setActiveTab] = useState<'facts' | 'habitat' | 'conservation'>('facts');
|
||||
|
||||
// Get burrowing owl data based on stream ID
|
||||
const getWildlifeData = () => {
|
||||
switch (id) {
|
||||
case "1":
|
||||
return {
|
||||
species: "Burrowing Owl",
|
||||
scientificName: "Athene cunicularia",
|
||||
location: "Cape Coral, FL",
|
||||
facts: [
|
||||
"Burrowing owls are small, long-legged owls that nest underground in burrows",
|
||||
"Unlike most owls, they are active during the day (diurnal)",
|
||||
"They stand about 9 inches tall and have bright yellow eyes",
|
||||
"The City of Cape Coral has designated the burrowing owl as its official city bird"
|
||||
],
|
||||
habitat: "Cape Coral has the largest population of burrowing owls in Florida. They prefer open areas with low vegetation such as prairies, grasslands, and open areas of urban development. CCFW volunteers maintain over 2,500 burrows throughout Cape Coral.",
|
||||
conservation: "Burrowing owls are listed as a state-threatened species in Florida. Development of their habitats is the biggest threat to their survival. CCFW works to protect and maintain burrows, educate the public, and collaborate with local authorities to ensure these birds have safe places to nest.",
|
||||
ccfwLink: "https://ccfriendsofwildlife.org/burrowing-owls/"
|
||||
};
|
||||
case "2":
|
||||
return {
|
||||
species: "Burrowing Owl",
|
||||
scientificName: "Athene cunicularia",
|
||||
location: "Cape Coral, FL",
|
||||
facts: [
|
||||
"Burrowing owls create underground burrows that can be up to 30 feet long",
|
||||
"They often use burrows created by other animals like prairie dogs or armadillos",
|
||||
"These owls are known for their distinctive 'bobblehead' behavior when curious",
|
||||
"They can live up to 9 years in the wild with proper habitat protection"
|
||||
],
|
||||
habitat: "Burrowing owls prefer open, grassy areas with sparse vegetation. They are commonly found in prairies, agricultural fields, and urban areas with suitable open spaces. The owls dig their own burrows or modify existing ones.",
|
||||
conservation: "Habitat loss from urban development is the primary threat to burrowing owls. CCFW's burrow maintenance program helps protect existing burrows and creates artificial burrows to support the owl population in Cape Coral.",
|
||||
ccfwLink: "https://ccfriendsofwildlife.org/burrowing-owls/"
|
||||
};
|
||||
case "3":
|
||||
return {
|
||||
species: "Burrowing Owl",
|
||||
scientificName: "Athene cunicularia",
|
||||
location: "Cape Coral, FL",
|
||||
facts: [
|
||||
"Burrowing owls are Florida's smallest owl species",
|
||||
"They have long legs adapted for walking and running on the ground",
|
||||
"Their diet consists mainly of insects, small mammals, and reptiles",
|
||||
"They are the only owl species that nests exclusively underground"
|
||||
],
|
||||
habitat: "These unique owls inhabit open grasslands, pastures, and urban areas with low vegetation. They are particularly well-adapted to the Florida landscape and have thrived in areas where other wildlife has declined.",
|
||||
conservation: "CCFW volunteers monitor and maintain over 2,500 burrows in Cape Coral. The organization's educational programs help the community understand the importance of protecting these threatened birds and their habitats.",
|
||||
ccfwLink: "https://ccfriendsofwildlife.org/burrowing-owls/"
|
||||
};
|
||||
default:
|
||||
return {
|
||||
species: "Burrowing Owl",
|
||||
scientificName: "Athene cunicularia",
|
||||
location: "Cape Coral, FL",
|
||||
facts: [
|
||||
"Burrowing owls are the official city bird of Cape Coral",
|
||||
"They are diurnal, meaning they are active during the day",
|
||||
"These owls have distinctive long legs and bright yellow eyes",
|
||||
"CCFW maintains over 2,500 burrows to protect this threatened species"
|
||||
],
|
||||
habitat: "Cape Coral provides ideal habitat for burrowing owls with its mix of urban development and open spaces. The city has the largest population of burrowing owls in Florida due to successful conservation efforts.",
|
||||
conservation: "Cape Coral Friends of Wildlife works tirelessly to protect burrowing owls through habitat preservation, burrow maintenance, public education, and collaboration with local authorities.",
|
||||
ccfwLink: "https://ccfriendsofwildlife.org/burrowing-owls/"
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
const wildlifeData = getWildlifeData();
|
||||
|
||||
return (
|
||||
<Card className="bg-black/30 border-accent/50 backdrop-blur-sm">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-accent neon-glow">About This Livestream</CardTitle>
|
||||
<Card className="border-ccfw-teal/30 bg-gradient-to-b from-ccfw-beige/20 to-ccfw-beige/5 backdrop-blur-sm">
|
||||
<CardHeader className="border-b border-ccfw-teal/20 bg-ccfw-beige/10">
|
||||
<CardTitle className="text-ccfw-teal">About {wildlifeData.species}</CardTitle>
|
||||
<CardDescription className="text-ccfw-maroon font-medium italic">
|
||||
{wildlifeData.scientificName && (
|
||||
<>{wildlifeData.scientificName} • </>
|
||||
)}
|
||||
{wildlifeData.location}
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-sm text-foreground/80">
|
||||
This livestream (ID: {id}) showcases the natural habitat and behavior of wildlife in Florida.
|
||||
By observing these animals in their natural environment, we can learn more about their needs and how to protect them.
|
||||
<CardContent className="space-y-4 pt-4">
|
||||
<div className="flex space-x-1 bg-ccfw-beige/10 p-1 rounded-md">
|
||||
<Button
|
||||
variant="ghost"
|
||||
className={`flex-1 text-xs h-8 ${activeTab === 'facts' ? 'bg-ccfw-teal/20 text-ccfw-teal' : 'text-ccfw-maroon hover:text-ccfw-teal hover:bg-ccfw-teal/10'}`}
|
||||
onClick={() => setActiveTab('facts')}
|
||||
>
|
||||
Facts
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className={`flex-1 text-xs h-8 ${activeTab === 'habitat' ? 'bg-ccfw-teal/20 text-ccfw-teal' : 'text-ccfw-maroon hover:text-ccfw-teal hover:bg-ccfw-teal/10'}`}
|
||||
onClick={() => setActiveTab('habitat')}
|
||||
>
|
||||
Habitat
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
className={`flex-1 text-xs h-8 ${activeTab === 'conservation' ? 'bg-ccfw-teal/20 text-ccfw-teal' : 'text-ccfw-maroon hover:text-ccfw-teal hover:bg-ccfw-teal/10'}`}
|
||||
onClick={() => setActiveTab('conservation')}
|
||||
>
|
||||
Conservation
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="min-h-[180px]">
|
||||
{activeTab === 'facts' && (
|
||||
<div className="space-y-2">
|
||||
<ul className="list-disc list-inside space-y-2 text-sm text-ccfw-maroon font-medium">
|
||||
{wildlifeData.facts.map((fact, index) => (
|
||||
<li key={index}>{fact}</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 'habitat' && (
|
||||
<div className="space-y-2">
|
||||
<p className="text-sm text-ccfw-maroon font-medium">{wildlifeData.habitat}</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{activeTab === 'conservation' && (
|
||||
<div className="space-y-3">
|
||||
<p className="text-sm text-ccfw-maroon font-medium">{wildlifeData.conservation}</p>
|
||||
|
||||
<div className="bg-ccfw-beige/10 p-3 rounded-md border border-ccfw-teal/20 flex flex-col sm:flex-row items-center gap-3">
|
||||
<div className="bg-ccfw-gold/20 p-2 rounded-full">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-ccfw-gold" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div className="text-center sm:text-left">
|
||||
<p className="text-sm text-ccfw-maroon font-medium">
|
||||
<span className="font-medium text-ccfw-teal">How you can help:</span> Join the Cape Coral Friends of Wildlife in their mission to preserve and protect these incredible creatures.
|
||||
</p>
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/volunteer/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-xs text-ccfw-teal hover:text-ccfw-coral transition-colors"
|
||||
>
|
||||
Learn about volunteer opportunities
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<div className="pt-3 border-t border-ccfw-teal/20 flex justify-between items-center">
|
||||
<span className="text-xs text-ccfw-maroon font-medium">Updated daily</span>
|
||||
<a
|
||||
href={wildlifeData.ccfwLink}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-ccfw-teal text-xs hover:text-ccfw-coral transition-colors flex items-center gap-1"
|
||||
>
|
||||
Learn More
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
|
||||
@ -3,10 +3,43 @@
|
||||
@tailwind utilities;
|
||||
|
||||
:root {
|
||||
--background: 10 10 10;
|
||||
/* CCFW Colors */
|
||||
--background: 25 25 25;
|
||||
--foreground: 230 230 230;
|
||||
--accent: 0 255 170;
|
||||
--accent-foreground: 0 0 0;
|
||||
--muted: 50 50 50;
|
||||
--muted-foreground: 180 180 180;
|
||||
|
||||
/* Teal/turquoise from CCFW site */
|
||||
--accent: 0 130 167;
|
||||
--accent-foreground: 255 255 255;
|
||||
|
||||
/* CCFW Colors */
|
||||
--card: 233 230 223;
|
||||
--card-foreground: 51 51 51;
|
||||
|
||||
/* Teal/turquoise from CCFW */
|
||||
--primary: 0 130 167;
|
||||
--primary-foreground: 255 255 255;
|
||||
|
||||
/* CCFW Yellow/Gold */
|
||||
--secondary: 246 202 66;
|
||||
--secondary-foreground: 51 51 51;
|
||||
|
||||
/* Coral red from CCFW site */
|
||||
--destructive: 255 133 106;
|
||||
--destructive-foreground: 255 255 255;
|
||||
|
||||
/* CCFW Colors */
|
||||
--border: 204 204 204;
|
||||
--input: 233 230 223;
|
||||
--ring: 0 130 167;
|
||||
|
||||
/* Additional CCFW colors */
|
||||
--ccfw-gold: 246 202 66;
|
||||
--ccfw-teal: 0 130 167;
|
||||
--ccfw-coral: 255 133 106;
|
||||
--ccfw-beige: 233 230 223;
|
||||
--ccfw-maroon: 88 40 67;
|
||||
}
|
||||
|
||||
body {
|
||||
|
||||
@ -1,21 +1,70 @@
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import LiveStream from '@/app/components/LiveStream';
|
||||
import DonationPanel from '@/app/components/DonationPanel';
|
||||
import OwlInfo from '@/app/components/OwlInfo';
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent } from "@/components/ui/card";
|
||||
|
||||
// This would come from an API or database in a real app
|
||||
const livestreamsData = [
|
||||
{
|
||||
id: "1",
|
||||
name: "Cape Coral Burrowing Owl",
|
||||
location: "Cape Coral, FL",
|
||||
status: "Live",
|
||||
viewers: 128,
|
||||
description: "Watch these unique ground-dwelling owls at their burrows in Cape Coral. These protected birds are the official city bird of Cape Coral!"
|
||||
},
|
||||
{
|
||||
id: "2",
|
||||
name: "Sanibel Island Osprey",
|
||||
location: "Sanibel Island, FL",
|
||||
status: "Live",
|
||||
viewers: 86,
|
||||
description: "Observe ospreys building nests and hunting for fish around Sanibel Island."
|
||||
},
|
||||
{
|
||||
id: "3",
|
||||
name: "Everglades Alligator",
|
||||
location: "Everglades National Park, FL",
|
||||
status: "Offline",
|
||||
viewers: 0,
|
||||
description: "Temporarily offline. Usually shows alligators in their natural habitat in the Everglades."
|
||||
},
|
||||
];
|
||||
|
||||
export default function LivestreamPage({ params }: { params: { id: string } }) {
|
||||
// In a real app, you'd fetch the livestream data based on the ID
|
||||
const streamData = {
|
||||
// Find the stream data based on the ID
|
||||
const streamData = livestreamsData.find(stream => stream.id === params.id) || {
|
||||
id: params.id,
|
||||
name: `Livestream ${params.id}`,
|
||||
name: `Wildlife Livestream ${params.id}`,
|
||||
location: "Florida",
|
||||
status: "Live",
|
||||
viewers: Math.floor(Math.random() * 100) + 50,
|
||||
description: "Experience the natural beauty of Florida's wildlife."
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-foreground">
|
||||
<header className="bg-black/50 backdrop-blur-sm">
|
||||
<div className="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-4xl font-bold neon-glow text-accent">{streamData.name}</h1>
|
||||
<header className="bg-ccfw-beige/90 backdrop-blur-sm sticky top-0 z-10 border-b border-ccfw-teal/20">
|
||||
<div className="max-w-7xl mx-auto py-4 px-4 sm:px-6 lg:px-8 flex justify-between items-center">
|
||||
<div>
|
||||
<Button variant="ghost" className="text-ccfw-teal mb-2" asChild>
|
||||
<Link href="/">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5 mr-1 inline" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 19l-7-7 7-7" />
|
||||
</svg>
|
||||
Back to all streams
|
||||
</Link>
|
||||
</Button>
|
||||
<h1 className="text-3xl font-bold text-ccfw-teal">{streamData.name}</h1>
|
||||
<p className="text-ccfw-maroon text-sm mt-1">{streamData.location}</p>
|
||||
</div>
|
||||
<div className="flex items-center gap-3">
|
||||
<div className={`h-3 w-3 rounded-full ${streamData.status === 'Live' ? 'bg-ccfw-coral animate-pulse' : 'bg-gray-500'}`}></div>
|
||||
<span className="text-sm font-medium text-ccfw-maroon font-semibold">{streamData.status}</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
|
||||
@ -23,14 +72,113 @@ export default function LivestreamPage({ params }: { params: { id: string } }) {
|
||||
<div className="grid grid-cols-1 lg:grid-cols-3 gap-6">
|
||||
<div className="lg:col-span-2">
|
||||
<LiveStream id={streamData.id} />
|
||||
|
||||
<div className="mt-6">
|
||||
<Card className="border-ccfw-teal/30 bg-gradient-to-b from-ccfw-beige/20 to-ccfw-beige/5 backdrop-blur-sm">
|
||||
<CardContent className="pt-6">
|
||||
<div className="flex items-start gap-4">
|
||||
<div className="bg-ccfw-teal/10 p-3 rounded-full">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-ccfw-teal" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-lg font-medium text-ccfw-teal mb-2">About this livestream</h3>
|
||||
<p className="text-sm text-ccfw-maroon font-medium">
|
||||
This livestream is provided by Cape Coral Friends of Wildlife, a volunteer organization dedicated to the protection and preservation of local wildlife. These cameras help researchers monitor wildlife behavior while allowing the public to connect with nature.
|
||||
</p>
|
||||
<p className="text-sm mt-2">
|
||||
<a
|
||||
href={`https://ccfriendsofwildlife.org/burrowing-owls/`}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-ccfw-teal hover:text-ccfw-coral transition-colors underline"
|
||||
>
|
||||
Learn more about our conservation efforts
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-6">
|
||||
<DonationPanel id={streamData.id} />
|
||||
<OwlInfo id={streamData.id} />
|
||||
|
||||
<Card className="border-ccfw-teal/30 bg-gradient-to-b from-ccfw-beige/20 to-ccfw-beige/5 backdrop-blur-sm overflow-hidden">
|
||||
<CardContent className="pt-6">
|
||||
<h3 className="text-lg font-medium text-ccfw-teal mb-4">Get Involved</h3>
|
||||
<ul className="space-y-3">
|
||||
<li className="flex items-center gap-3">
|
||||
<div className="bg-ccfw-gold/20 p-2 rounded-full">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4 text-ccfw-gold" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M21 13.255A23.931 23.931 0 0112 15c-3.183 0-6.22-.62-9-1.745M16 6V4a2 2 0 00-2-2h-4a2 2 0 00-2 2v2m4 6h.01M5 20h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/volunteer/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sm text-ccfw-maroon font-medium hover:text-ccfw-teal transition-colors"
|
||||
>
|
||||
Volunteer with CCFW
|
||||
</a>
|
||||
</li>
|
||||
<li className="flex items-center gap-3">
|
||||
<div className="bg-ccfw-teal/20 p-2 rounded-full">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4 text-ccfw-teal" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/events-and-programs/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="text-sm text-ccfw-maroon font-medium hover:text-ccfw-teal transition-colors"
|
||||
>
|
||||
Attend an Event
|
||||
</a>
|
||||
</li>
|
||||
<li className="flex items-center gap-3">
|
||||
<div className="bg-ccfw-coral/20 p-2 rounded-full">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-4 w-4 text-ccfw-coral" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 8l7.89 5.26a2 2 0 002.22 0L21 8M5 19h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" />
|
||||
</svg>
|
||||
</div>
|
||||
<a
|
||||
href="mailto:info@ccfriendsofwildlife.org"
|
||||
className="text-sm text-ccfw-maroon font-medium hover:text-ccfw-teal transition-colors"
|
||||
>
|
||||
Contact CCFW
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer className="bg-ccfw-beige/90 text-ccfw-maroon py-8 mt-12">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 text-center">
|
||||
<p className="text-sm">
|
||||
© {new Date().getFullYear()} Cape Coral Friends of Wildlife. All rights reserved.
|
||||
</p>
|
||||
<p className="text-sm mt-2">
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="hover:text-ccfw-teal transition-colors"
|
||||
>
|
||||
Visit our main website
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
643
app/page.tsx
643
app/page.tsx
@ -1,59 +1,215 @@
|
||||
import React from 'react';
|
||||
import Link from 'next/link';
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card";
|
||||
import { Card, CardContent, CardHeader, CardTitle, CardDescription, CardFooter } from "@/components/ui/card";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Badge } from "@/components/ui/badge";
|
||||
|
||||
// This would typically come from an API or database
|
||||
const livestreams = [
|
||||
{ id: 1, name: "Cape Coral Burrowing Owl", location: "Cape Coral, FL", status: "Live" },
|
||||
{ id: 2, name: "Sanibel Island Osprey", location: "Sanibel Island, FL", status: "Live" },
|
||||
{ id: 3, name: "Everglades Alligator", location: "Everglades National Park, FL", status: "Offline" },
|
||||
// ... add more livestreams as needed
|
||||
{
|
||||
id: 1,
|
||||
name: "Cape Coral Burrowing Owl",
|
||||
location: "Cape Coral, FL",
|
||||
status: "Live",
|
||||
viewers: 128,
|
||||
description: "Watch these unique ground-dwelling owls at their burrows in Cape Coral. These protected birds are the official city bird of Cape Coral!"
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
name: "Burrowing Owl Habitat",
|
||||
location: "Cape Coral, FL",
|
||||
status: "Live",
|
||||
viewers: 95,
|
||||
description: "Observe burrowing owls in their natural habitat. Watch them hunt, nest, and interact with their environment."
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
name: "Owl Burrow Monitoring",
|
||||
location: "Cape Coral, FL",
|
||||
status: "Live",
|
||||
viewers: 67,
|
||||
description: "Monitor active burrowing owl burrows and learn about CCFW's conservation efforts to protect these amazing birds."
|
||||
},
|
||||
];
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div className="min-h-screen bg-background text-foreground">
|
||||
<header className="bg-black/50 backdrop-blur-sm sticky top-0 z-10">
|
||||
<div className="max-w-7xl mx-auto py-4 px-4 sm:px-6 lg:px-8">
|
||||
<h1 className="text-3xl font-bold text-accent">Florida Wildlife Livestreams</h1>
|
||||
<header className="bg-gradient-to-r from-ccfw-beige/95 via-ccfw-beige/90 to-ccfw-beige/95 backdrop-blur-md sticky top-0 z-10 border-b border-ccfw-teal/30 shadow-sm">
|
||||
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8">
|
||||
<div className="flex justify-between items-center h-16">
|
||||
{/* Logo and Brand */}
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 bg-ccfw-teal/20 rounded-full blur-sm"></div>
|
||||
<div className="relative bg-gradient-to-br from-ccfw-teal to-ccfw-maroon p-2 rounded-full">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-white" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h1 className="text-xl font-bold text-ccfw-teal tracking-tight">CCFW Livestreams</h1>
|
||||
<p className="text-xs text-ccfw-maroon font-semibold">Cape Coral Friends of Wildlife</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Navigation Actions */}
|
||||
<div className="flex items-center space-x-3">
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/support/membership/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group relative px-4 py-2 bg-gradient-to-r from-ccfw-teal to-ccfw-maroon text-white font-medium rounded-lg shadow-sm hover:shadow-md transition-all duration-200 transform hover:scale-105"
|
||||
>
|
||||
<span className="relative z-10">Join/Renew</span>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-ccfw-maroon to-ccfw-teal rounded-lg opacity-0 group-hover:opacity-100 transition-opacity duration-200"></div>
|
||||
</a>
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/volunteer/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group relative px-4 py-2 bg-gradient-to-r from-ccfw-coral to-orange-400 text-white font-medium rounded-lg shadow-sm hover:shadow-md transition-all duration-200 transform hover:scale-105"
|
||||
>
|
||||
<span className="relative z-10">Volunteer</span>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-orange-400 to-ccfw-coral rounded-lg opacity-0 group-hover:opacity-100 transition-opacity duration-200"></div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<main className="max-w-7xl mx-auto py-6 sm:px-6 lg:px-8">
|
||||
<div className="px-4 py-6 sm:px-0 space-y-12">
|
||||
<section>
|
||||
<Card className="bg-black/30 border-accent/50 backdrop-blur-sm">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-2xl text-accent">Welcome to Florida's Wild Side</CardTitle>
|
||||
<CardDescription className="text-foreground/80">
|
||||
Explore the diverse ecosystems of Florida through our live cameras.
|
||||
{/* Hero Section */}
|
||||
<section className="relative">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-ccfw-teal/5 via-transparent to-ccfw-maroon/5 rounded-3xl"></div>
|
||||
<Card className="relative border-0 bg-gradient-to-br from-ccfw-maroon/90 via-ccfw-maroon/85 to-ccfw-maroon/90 backdrop-blur-md overflow-hidden shadow-2xl">
|
||||
<div className="absolute inset-0 bg-[url('https://ccfriendsofwildlife.org/wp-content/uploads/2020/07/Featured-image-home-page-1080x675.jpg')] opacity-15 bg-center bg-cover mix-blend-overlay"></div>
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/20 via-transparent to-transparent"></div>
|
||||
|
||||
<CardHeader className="relative z-10 pb-8">
|
||||
<div className="flex items-center space-x-3 mb-4">
|
||||
<div className="h-1 w-12 bg-gradient-to-r from-ccfw-gold to-ccfw-coral rounded-full"></div>
|
||||
<span className="text-white text-sm font-medium tracking-wider uppercase">Live Wildlife Streams</span>
|
||||
</div>
|
||||
<CardTitle className="text-4xl md:text-5xl font-bold text-white leading-tight mb-4">
|
||||
Cape Coral Friends of
|
||||
<span className="block text-transparent bg-gradient-to-r from-ccfw-gold via-ccfw-coral to-orange-400 bg-clip-text">
|
||||
Wildlife Livestreams
|
||||
</span>
|
||||
</CardTitle>
|
||||
<CardDescription className="text-white/90 text-xl font-medium leading-relaxed">
|
||||
Dedicated to Protection, Preservation and Education
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-foreground/80 mb-4">
|
||||
From the unique burrowing owls of Cape Coral to the majestic ospreys of Sanibel Island and the iconic alligators of the Everglades, witness the beauty of Florida's wildlife in real-time.
|
||||
|
||||
<CardContent className="relative z-10 space-y-6">
|
||||
<p className="text-white text-lg leading-relaxed font-medium">
|
||||
Discover the fascinating world of <span className="text-ccfw-gold font-semibold">burrowing owls</span>, the official city bird of Cape Coral.
|
||||
These unique ground-dwelling owls are active during the day and nest underground in burrows throughout our community.
|
||||
</p>
|
||||
<p className="text-foreground/80">
|
||||
Our livestreams offer a window into the natural world, promoting conservation awareness and providing valuable data for researchers and wildlife enthusiasts alike.
|
||||
<p className="text-white/90 text-lg leading-relaxed">
|
||||
Cape Coral Friends of Wildlife is dedicated to protecting these threatened birds through habitat preservation, burrow maintenance, and community education. With over 2,500 burrows maintained by our volunteers, we ensure these amazing owls thrive in our urban environment.
|
||||
</p>
|
||||
|
||||
<div className="flex flex-col sm:flex-row gap-4 pt-4">
|
||||
<div className="flex items-center space-x-6 text-white/80">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="h-2 w-2 bg-ccfw-coral rounded-full animate-pulse"></div>
|
||||
<span className="text-sm font-medium">Live 24/7</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<svg className="h-4 w-4 text-ccfw-gold" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M3 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 4a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z" clipRule="evenodd" />
|
||||
</svg>
|
||||
<span className="text-sm font-medium">HD Quality</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<svg className="h-4 w-4 text-ccfw-teal" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clipRule="evenodd" />
|
||||
</svg>
|
||||
<span className="text-sm font-medium">Cape Coral, FL</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
|
||||
<CardFooter className="relative z-10 pt-6">
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/about-us/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group inline-flex items-center space-x-2 px-6 py-3 bg-gradient-to-r from-ccfw-gold to-ccfw-coral text-white font-semibold rounded-xl shadow-lg hover:shadow-xl transition-all duration-200 transform hover:scale-105"
|
||||
>
|
||||
<span>Learn more about CCFW</span>
|
||||
<svg className="h-4 w-4 transition-transform group-hover:translate-x-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M17 8l4 4m0 0l-4 4m4-4H3" />
|
||||
</svg>
|
||||
</a>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-semibold text-accent mb-4">Featured Ecosystems</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
||||
{['Cape Coral', 'Sanibel Island', 'Everglades'].map((ecosystem) => (
|
||||
<Card key={ecosystem} className="bg-black/30 border-accent/50 backdrop-blur-sm">
|
||||
<CardHeader>
|
||||
<CardTitle className="text-accent">{ecosystem}</CardTitle>
|
||||
{/* Featured Owls Section */}
|
||||
<section className="space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<div className="inline-flex items-center space-x-3">
|
||||
<div className="h-1 w-8 bg-gradient-to-r from-ccfw-teal to-ccfw-maroon rounded-full"></div>
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-ccfw-teal tracking-tight">Featured Owls</h2>
|
||||
<div className="h-1 w-8 bg-gradient-to-r from-ccfw-maroon to-ccfw-teal rounded-full"></div>
|
||||
</div>
|
||||
<div className="flex items-center justify-center space-x-6 text-sm text-white font-medium">
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="h-2 w-2 bg-ccfw-teal rounded-full"></div>
|
||||
<span>Founded in 2001</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2">
|
||||
<svg className="h-4 w-4 text-ccfw-gold" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M13 6a3 3 0 11-6 0 3 3 0 016 0zM18 8a2 2 0 11-4 0 2 2 0 014 0zM14 15a4 4 0 00-8 0v3h8v-3z" />
|
||||
</svg>
|
||||
<span>500+ Members</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-8">
|
||||
{[
|
||||
{
|
||||
name: 'Burrowing Owl Facts',
|
||||
icon: '🦉',
|
||||
color: 'from-ccfw-teal to-ccfw-maroon',
|
||||
description: "Burrowing owls are small, long-legged owls that nest underground in burrows. Unlike most owls, they are active during the day and have bright yellow eyes. The City of Cape Coral has designated the burrowing owl as its official city bird."
|
||||
},
|
||||
{
|
||||
name: 'Owl Conservation',
|
||||
icon: '🌱',
|
||||
color: 'from-ccfw-maroon to-ccfw-teal',
|
||||
description: "CCFW volunteers maintain over 2,500 burrows throughout Cape Coral. These unique birds face threats from habitat loss and development. Our conservation efforts protect these amazing ground-dwelling owls."
|
||||
},
|
||||
{
|
||||
name: 'Owl Habitat',
|
||||
icon: '🏞️',
|
||||
color: 'from-ccfw-gold to-ccfw-coral',
|
||||
description: "Burrowing owls prefer open areas with low vegetation such as prairies, grasslands, and open areas of urban development. They create burrows that provide shelter for many other wildlife species as well."
|
||||
}
|
||||
].map((owlFeature) => (
|
||||
<Card key={owlFeature.name} className="group relative border-0 bg-gradient-to-br from-white/80 to-white/60 backdrop-blur-sm shadow-lg hover:shadow-xl transition-all duration-300 transform hover:scale-105 overflow-hidden">
|
||||
<div className={`absolute inset-0 bg-gradient-to-br ${owlFeature.color} opacity-0 group-hover:opacity-10 transition-opacity duration-300`}></div>
|
||||
|
||||
<CardHeader className="relative z-10 pb-4">
|
||||
<div className="flex items-center space-x-3 mb-3">
|
||||
<div className="text-3xl group-hover:scale-110 transition-transform duration-200">{owlFeature.icon}</div>
|
||||
<div>
|
||||
<CardTitle className="text-xl font-bold text-ccfw-teal group-hover:text-ccfw-maroon transition-colors">
|
||||
{owlFeature.name}
|
||||
</CardTitle>
|
||||
</div>
|
||||
</div>
|
||||
<div className={`h-0.5 w-full bg-gradient-to-r ${owlFeature.color} rounded-full`}></div>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<p className="text-foreground/80">
|
||||
{ecosystem === 'Cape Coral' && "Home to the largest population of burrowing owls in Florida, supporting these ground-dwelling birds."}
|
||||
{ecosystem === 'Sanibel Island' && "A barrier island known for its shell beaches and wildlife refuges, crucial for ospreys and coastal birds."}
|
||||
{ecosystem === 'Everglades' && "The largest subtropical wilderness in the US, home to diverse species including the American alligator."}
|
||||
|
||||
<CardContent className="relative z-10">
|
||||
<p className="text-ccfw-maroon leading-relaxed font-medium">
|
||||
{owlFeature.description}
|
||||
</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
@ -61,31 +217,424 @@ export default function Home() {
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<h2 className="text-2xl font-semibold text-accent mb-4">Live Cameras</h2>
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{livestreams.map((stream) => (
|
||||
<Card key={stream.id} className="bg-black/30 border-accent/50 backdrop-blur-sm hover:bg-black/50 transition-colors">
|
||||
<CardHeader>
|
||||
<div className="flex justify-between items-center">
|
||||
<CardTitle className="text-accent">{stream.name}</CardTitle>
|
||||
<Badge variant={stream.status === 'Live' ? 'default' : 'secondary'}>
|
||||
{stream.status}
|
||||
</Badge>
|
||||
{/* Live Cameras Section */}
|
||||
<section className="space-y-8">
|
||||
<div className="text-center space-y-4">
|
||||
<div className="inline-flex items-center space-x-3">
|
||||
<div className="h-1 w-8 bg-gradient-to-r from-ccfw-coral to-ccfw-gold rounded-full"></div>
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-ccfw-teal tracking-tight">Live Cameras</h2>
|
||||
<div className="h-1 w-8 bg-gradient-to-r from-ccfw-gold to-ccfw-coral rounded-full"></div>
|
||||
</div>
|
||||
<CardDescription className="text-foreground/80">{stream.location}</CardDescription>
|
||||
<div className="flex items-center justify-center space-x-2 text-sm text-white font-medium">
|
||||
<svg className="h-4 w-4 text-ccfw-teal" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M4 3a2 2 0 00-2 2v8a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4zm3 2l3 3-3 3V8z" clipRule="evenodd" />
|
||||
</svg>
|
||||
<span>Powered by</span>
|
||||
<span className="font-bold text-transparent bg-gradient-to-r from-ccfw-gold to-ccfw-coral bg-clip-text">
|
||||
CCFW
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
|
||||
{livestreams.map((stream) => (
|
||||
<Card key={stream.id} className="group relative border-0 bg-gradient-to-br from-white/90 to-white/70 backdrop-blur-sm shadow-lg hover:shadow-2xl transition-all duration-300 transform hover:scale-105 hover:-translate-y-2 overflow-hidden">
|
||||
{/* Status Indicator */}
|
||||
<div className="absolute top-4 right-4 z-20">
|
||||
<div className={`flex items-center space-x-2 px-3 py-1.5 rounded-full backdrop-blur-sm border ${
|
||||
stream.status === 'Live'
|
||||
? 'bg-emerald-500/20 border-emerald-400/30 text-emerald-700'
|
||||
: 'bg-gray-600/20 border-gray-500/30 text-gray-700'
|
||||
}`}>
|
||||
<div className={`h-2 w-2 rounded-full ${
|
||||
stream.status === 'Live' ? 'bg-emerald-500 animate-pulse' : 'bg-gray-400'
|
||||
}`}></div>
|
||||
<span className="text-xs font-bold tracking-wide uppercase">{stream.status}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Background Gradient Overlay */}
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-ccfw-teal/5 via-transparent to-ccfw-maroon/5 opacity-0 group-hover:opacity-100 transition-opacity duration-300"></div>
|
||||
|
||||
{/* Camera Preview Mockup */}
|
||||
<div className="relative h-48 bg-gradient-to-br from-ccfw-teal/10 to-ccfw-maroon/10 flex items-center justify-center overflow-hidden">
|
||||
<div className="absolute inset-0 bg-gradient-to-t from-black/20 to-transparent"></div>
|
||||
<div className="relative z-10 text-center space-y-3">
|
||||
<div className="mx-auto w-16 h-16 bg-white/20 backdrop-blur-sm rounded-full flex items-center justify-center">
|
||||
<svg className="h-8 w-8 text-ccfw-teal" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M2 6a2 2 0 012-2h6a2 2 0 012 2v8a2 2 0 01-2 2H4a2 2 0 01-2-2V6zM14.553 7.106A1 1 0 0014 8v4a1 1 0 00.553.894l2 1A1 1 0 0018 13V7a1 1 0 00-1.447-.894l-2 1z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div className="text-white/80 text-sm font-medium">HD Live Stream</div>
|
||||
</div>
|
||||
|
||||
{/* Quality Badge */}
|
||||
<div className="absolute top-4 left-4 bg-black/60 text-white text-xs px-2 py-1 rounded backdrop-blur-sm">
|
||||
HD
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<CardHeader className="relative z-10 pt-6">
|
||||
<CardTitle className="text-xl font-bold text-ccfw-teal group-hover:text-ccfw-maroon transition-colors leading-tight">
|
||||
{stream.name}
|
||||
</CardTitle>
|
||||
<CardDescription className="text-ccfw-maroon font-medium flex items-center space-x-1">
|
||||
<svg className="h-4 w-4" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M5.05 4.05a7 7 0 119.9 9.9L10 18.9l-4.95-4.95a7 7 0 010-9.9zM10 11a2 2 0 100-4 2 2 0 000 4z" clipRule="evenodd" />
|
||||
</svg>
|
||||
<span>{stream.location}</span>
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<Button asChild className="w-full">
|
||||
<Link href={`/livestream/${stream.id}`}>Watch Now</Link>
|
||||
|
||||
<CardContent className="relative z-10 space-y-4">
|
||||
<p className="text-ccfw-maroon leading-relaxed font-medium text-sm">
|
||||
{stream.description}
|
||||
</p>
|
||||
|
||||
{/* Viewer Count & Quality */}
|
||||
<div className="flex justify-between items-center">
|
||||
<div className="flex items-center space-x-4 text-xs">
|
||||
{stream.status === 'Live' && (
|
||||
<div className="flex items-center space-x-1 text-ccfw-teal font-semibold">
|
||||
<svg className="h-3 w-3" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M13 6a3 3 0 11-6 0 3 3 0 016 0zM18 8a2 2 0 11-4 0 2 2 0 014 0zM14 15a4 4 0 00-8 0v3h8v-3z" />
|
||||
</svg>
|
||||
<span>{stream.viewers} viewers</span>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<div className="flex items-center space-x-1">
|
||||
<svg className="h-4 w-4 text-ccfw-gold" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M11.3 1.046A1 1 0 0112 2v5h4a1 1 0 01.82 1.573l-7 10A1 1 0 018 18v-5H4a1 1 0 01-.82-1.573l7-10a1 1 0 011.12-.38z" clipRule="evenodd" />
|
||||
</svg>
|
||||
<span className="text-xs font-semibold text-ccfw-maroon">HD</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Watch Button */}
|
||||
<Button
|
||||
asChild
|
||||
className={`w-full font-semibold py-3 rounded-xl shadow-md transition-all duration-200 ${
|
||||
stream.status === 'Live'
|
||||
? 'bg-gradient-to-r from-ccfw-teal to-ccfw-maroon text-white hover:shadow-lg hover:scale-105'
|
||||
: 'bg-gray-300 text-gray-600 cursor-not-allowed'
|
||||
}`}
|
||||
disabled={stream.status !== 'Live'}
|
||||
>
|
||||
<Link href={`/livestream/${stream.id}`} className="flex items-center justify-center space-x-2">
|
||||
{stream.status === 'Live' ? (
|
||||
<>
|
||||
<svg className="h-4 w-4" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M10 12l-6-4h12l-6 4z" />
|
||||
<path d="M10 8l6 4H4l6-4z" />
|
||||
</svg>
|
||||
<span>Watch Live</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<svg className="h-4 w-4" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8 7a1 1 0 00-1 1v4a1 1 0 001 1h4a1 1 0 001-1V8a1 1 0 00-1-1H8z" clipRule="evenodd" />
|
||||
</svg>
|
||||
<span>Offline</span>
|
||||
</>
|
||||
)}
|
||||
</Link>
|
||||
</Button>
|
||||
</CardContent>
|
||||
</Card>
|
||||
))}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Support Our Mission Section */}
|
||||
<section className="relative bg-gradient-to-br from-ccfw-beige/20 via-ccfw-beige/10 to-transparent p-8 rounded-3xl border border-ccfw-teal/30 shadow-lg overflow-hidden">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-ccfw-teal/5 to-ccfw-maroon/5"></div>
|
||||
|
||||
<div className="relative z-10 flex flex-col lg:flex-row gap-12 items-center">
|
||||
{/* Content Section */}
|
||||
<div className="lg:w-1/2 space-y-6">
|
||||
<div className="space-y-4">
|
||||
<div className="inline-flex items-center space-x-3">
|
||||
<div className="h-1 w-8 bg-gradient-to-r from-ccfw-teal to-ccfw-maroon rounded-full"></div>
|
||||
<h2 className="text-3xl md:text-4xl font-bold text-white tracking-tight">Support Our Mission</h2>
|
||||
</div>
|
||||
<p className="text-lg text-white leading-relaxed font-medium">
|
||||
Cape Coral Friends of Wildlife is a volunteer organization founded in 2001. With over 500 members and an engaged group of volunteers, we work to preserve and enhance the habitats of protected wildlife.
|
||||
</p>
|
||||
<p className="text-lg text-white/90 leading-relaxed font-medium">
|
||||
Your support helps us continue our conservation efforts and educational programs that benefit the unique wildlife of Southwest Florida.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Action Buttons */}
|
||||
<div className="flex flex-col sm:flex-row gap-4">
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/support/membership/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group relative px-6 py-3 bg-gradient-to-r from-ccfw-gold to-amber-500 text-white font-bold rounded-xl shadow-lg hover:shadow-xl transition-all duration-200 transform hover:scale-105 overflow-hidden"
|
||||
>
|
||||
<span className="relative z-10 flex items-center justify-center space-x-2">
|
||||
<svg className="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M13 6a3 3 0 11-6 0 3 3 0 016 0zM18 8a2 2 0 11-4 0 2 2 0 014 0zM14 15a4 4 0 00-8 0v3h8v-3z" />
|
||||
</svg>
|
||||
<span>Become a Member</span>
|
||||
</span>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-amber-500 to-ccfw-gold rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-200"></div>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/donate-to-ccfw/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group relative px-6 py-3 bg-gradient-to-r from-ccfw-coral to-rose-500 text-white font-bold rounded-xl shadow-lg hover:shadow-xl transition-all duration-200 transform hover:scale-105 overflow-hidden"
|
||||
>
|
||||
<span className="relative z-10 flex items-center justify-center space-x-2">
|
||||
<svg className="h-5 w-5" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M3.172 5.172a4 4 0 015.656 0L10 6.343l1.172-1.171a4 4 0 115.656 5.656L10 17.657l-6.828-6.829a4 4 0 010-5.656z" clipRule="evenodd" />
|
||||
</svg>
|
||||
<span>Donate Today</span>
|
||||
</span>
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-rose-500 to-ccfw-coral rounded-xl opacity-0 group-hover:opacity-100 transition-opacity duration-200"></div>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Stats Card */}
|
||||
<div className="lg:w-1/2 flex justify-center">
|
||||
<div className="relative w-full max-w-md">
|
||||
{/* Background Glow */}
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-ccfw-teal/20 to-ccfw-maroon/20 rounded-3xl blur-xl"></div>
|
||||
|
||||
<div className="relative bg-gradient-to-br from-white/90 to-white/70 backdrop-blur-sm p-8 rounded-3xl border border-white/30 shadow-xl">
|
||||
{/* Header */}
|
||||
<div className="text-center mb-8">
|
||||
<div className="inline-flex items-center space-x-2 mb-3">
|
||||
<svg className="h-6 w-6 text-ccfw-gold" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M6 2a1 1 0 00-1 1v1H4a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V6a2 2 0 00-2-2h-1V3a1 1 0 10-2 0v1H7V3a1 1 0 00-1-1zm0 5a1 1 0 000 2h8a1 1 0 100-2H6z" clipRule="evenodd" />
|
||||
</svg>
|
||||
<span className="text-sm font-bold text-white tracking-wider uppercase">Impact This Year</span>
|
||||
</div>
|
||||
<h3 className="text-2xl font-bold text-ccfw-teal">Volunteer Hours</h3>
|
||||
</div>
|
||||
|
||||
{/* Main Stat */}
|
||||
<div className="text-center mb-6">
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 bg-gradient-to-r from-ccfw-coral to-rose-400 rounded-full blur-2xl opacity-30"></div>
|
||||
<div className="relative text-7xl md:text-8xl font-black text-transparent bg-gradient-to-r from-ccfw-coral to-rose-500 bg-clip-text">
|
||||
836
|
||||
</div>
|
||||
</div>
|
||||
<p className="text-white font-semibold mt-2">And counting...</p>
|
||||
</div>
|
||||
|
||||
{/* CTA */}
|
||||
<div className="text-center">
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/volunteer/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="inline-flex items-center space-x-2 px-6 py-3 bg-gradient-to-r from-ccfw-teal to-ccfw-maroon text-white font-semibold rounded-xl shadow-md hover:shadow-lg transition-all duration-200 transform hover:scale-105"
|
||||
>
|
||||
<svg className="h-4 w-4" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
<path d="M9.049 2.927c.3-.921 1.603-.921 1.902 0l1.07 3.292a1 1 0 00.95.69h3.462c.969 0 1.371 1.24.588 1.81l-2.8 2.034a1 1 0 00-.364 1.118l1.07 3.292c.3.921-.755 1.688-1.54 1.118l-2.8-2.034a1 1 0 00-1.175 0l-2.8 2.034c-.784.57-1.838-.197-1.539-1.118l1.07-3.292a1 1 0 00-.364-1.118L2.98 8.72c-.783-.57-.38-1.81.588-1.81h3.461a1 1 0 00.951-.69l1.07-3.292z" />
|
||||
</svg>
|
||||
<span>Join Our Team</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</div>
|
||||
</main>
|
||||
{/* Modern Footer */}
|
||||
<footer className="relative bg-gradient-to-br from-ccfw-beige/90 via-ccfw-beige/95 to-white/90 backdrop-blur-sm mt-20 border-t border-ccfw-teal/30">
|
||||
<div className="absolute inset-0 bg-gradient-to-br from-ccfw-teal/5 to-transparent"></div>
|
||||
|
||||
<div className="relative max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
|
||||
{/* Main Footer Content */}
|
||||
<div className="grid grid-cols-1 md:grid-cols-4 gap-8 mb-12">
|
||||
{/* Organization Info */}
|
||||
<div className="md:col-span-2 space-y-6">
|
||||
<div className="flex items-center space-x-3">
|
||||
<div className="relative">
|
||||
<div className="absolute inset-0 bg-ccfw-teal/20 rounded-full blur-sm"></div>
|
||||
<div className="relative bg-gradient-to-br from-ccfw-teal to-ccfw-maroon p-2 rounded-full">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-6 w-6 text-white" viewBox="0 0 20 20" fill="currentColor">
|
||||
<path fillRule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm1-12a1 1 0 10-2 0v4a1 1 0 00.293.707l2.828 2.829a1 1 0 101.415-1.415L11 9.586V6z" clipRule="evenodd" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className="text-xl font-bold text-ccfw-teal tracking-tight">Cape Coral Friends of Wildlife</h3>
|
||||
<p className="text-sm text-ccfw-maroon font-medium">CCFW • Est. 2001</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p className="text-ccfw-maroon leading-relaxed font-medium max-w-md">
|
||||
A volunteer organization dedicated to the preservation of wildlife in Cape Coral, Florida. We protect and enhance habitats for protected species through education and conservation.
|
||||
</p>
|
||||
|
||||
<div className="flex items-center space-x-4">
|
||||
<div className="flex items-center space-x-2 bg-ccfw-teal/10 px-3 py-1.5 rounded-full">
|
||||
<svg className="h-4 w-4 text-ccfw-teal" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path fillRule="evenodd" d="M6.267 3.455a3.066 3.066 0 001.745-.723 3.066 3.066 0 013.976 0 3.066 3.066 0 001.745.723 3.066 3.066 0 012.812 2.812c.051.643.304 1.254.723 1.745a3.066 3.066 0 010 3.976 3.066 3.066 0 00-.723 1.745 3.066 3.066 0 01-2.812 2.812 3.066 3.066 0 00-1.745.723 3.066 3.066 0 01-3.976 0 3.066 3.066 0 00-1.745-.723 3.066 3.066 0 01-2.812-2.812 3.066 3.066 0 00-.723-1.745 3.066 3.066 0 010-3.976 3.066 3.066 0 00.723-1.745 3.066 3.066 0 012.812-2.812zm7.44 5.252a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clipRule="evenodd" />
|
||||
</svg>
|
||||
<span className="text-xs font-bold text-ccfw-teal">501(c)(3) Nonprofit</span>
|
||||
</div>
|
||||
<div className="flex items-center space-x-2 bg-ccfw-gold/20 px-3 py-1.5 rounded-full">
|
||||
<svg className="h-4 w-4 text-ccfw-gold" fill="currentColor" viewBox="0 0 20 20">
|
||||
<path d="M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z" />
|
||||
</svg>
|
||||
<span className="text-xs font-bold text-white">500+ Members</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Quick Links */}
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-lg font-bold text-ccfw-teal tracking-tight">Quick Links</h3>
|
||||
<ul className="space-y-3">
|
||||
<li>
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group flex items-center space-x-2 text-ccfw-maroon hover:text-ccfw-teal transition-colors font-medium"
|
||||
>
|
||||
<svg className="h-4 w-4 transition-transform group-hover:translate-x-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
||||
</svg>
|
||||
<span>Main Website</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/events-and-programs/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group flex items-center space-x-2 text-ccfw-maroon hover:text-ccfw-teal transition-colors font-medium"
|
||||
>
|
||||
<svg className="h-4 w-4 transition-transform group-hover:translate-x-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
||||
</svg>
|
||||
<span>Events & Programs</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/burrowing-owls/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group flex items-center space-x-2 text-ccfw-maroon hover:text-ccfw-teal transition-colors font-medium"
|
||||
>
|
||||
<svg className="h-4 w-4 transition-transform group-hover:translate-x-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
||||
</svg>
|
||||
<span>Burrowing Owls</span>
|
||||
</a>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://ccfriendsofwildlife.org/about-us/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group flex items-center space-x-2 text-ccfw-maroon hover:text-ccfw-teal transition-colors font-medium"
|
||||
>
|
||||
<svg className="h-4 w-4 transition-transform group-hover:translate-x-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
|
||||
</svg>
|
||||
<span>About Us</span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* Contact & Social */}
|
||||
<div className="space-y-4">
|
||||
<h3 className="text-lg font-bold text-ccfw-teal tracking-tight">Get In Touch</h3>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center space-x-3 p-3 bg-white/50 rounded-xl border border-ccfw-teal/20">
|
||||
<div className="bg-gradient-to-r from-ccfw-teal to-ccfw-maroon p-2 rounded-lg">
|
||||
<svg className="h-4 w-4 text-white" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M3 5a2 2 0 012-2h3.28a1 1 0 01.948.684l1.498 4.493a1 1 0 01-.502 1.21l-2.257 1.13a11.042 11.042 0 005.516 5.516l1.13-2.257a1 1 0 011.21-.502l4.493 1.498a1 1 0 01.684.949V19a2 2 0 01-2 2h-1C9.716 21 3 14.284 3 6V5z" />
|
||||
</svg>
|
||||
</div>
|
||||
<div>
|
||||
<p className="text-xs text-ccfw-maroon font-medium">Call Us</p>
|
||||
<a
|
||||
href="tel:239-980-2593"
|
||||
className="text-ccfw-maroon font-bold hover:text-ccfw-teal transition-colors"
|
||||
>
|
||||
(239) 980-2593
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="space-y-3">
|
||||
<p className="text-sm font-bold text-ccfw-teal tracking-wide uppercase">Follow Us</p>
|
||||
<div className="flex space-x-3">
|
||||
<a
|
||||
href="https://www.facebook.com/CCFriendsofWildlife"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group p-3 bg-gradient-to-r from-blue-600 to-blue-700 text-white rounded-xl shadow-md hover:shadow-lg transition-all duration-200 transform hover:scale-110"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M9 8h-3v4h3v12h5v-12h3.642l.358-4h-4v-1.667c0-.955.192-1.333 1.115-1.333h2.885v-5h-3.808c-3.596 0-5.192 1.583-5.192 4.615v3.385z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://www.instagram.com/ccfriendsofwildlife/"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group p-3 bg-gradient-to-r from-pink-500 via-red-500 to-yellow-500 text-white rounded-xl shadow-md hover:shadow-lg transition-all duration-200 transform hover:scale-110"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M12 2.163c3.204 0 3.584.012 4.85.07 3.252.148 4.771 1.691 4.919 4.919.058 1.265.069 1.645.069 4.849 0 3.205-.012 3.584-.069 4.849-.149 3.225-1.664 4.771-4.919 4.919-1.266.058-1.644.07-4.85.07-3.204 0-3.584-.012-4.849-.07-3.26-.149-4.771-1.699-4.919-4.92-.058-1.265-.07-1.644-.07-4.849 0-3.204.013-3.583.07-4.849.149-3.227 1.664-4.771 4.919-4.919 1.266-.057 1.645-.069 4.849-.069zm0-2.163c-3.259 0-3.667.014-4.947.072-4.358.2-6.78 2.618-6.98 6.98-.059 1.281-.073 1.689-.073 4.948 0 3.259.014 3.668.072 4.948.2 4.358 2.618 6.78 6.98 6.98 1.281.058 1.689.072 4.948.072 3.259 0 3.668-.014 4.948-.072 4.354-.2 6.782-2.618 6.979-6.98.059-1.28.073-1.689.073-4.948 0-3.259-.014-3.667-.072-4.947-.196-4.354-2.617-6.78-6.979-6.98-1.281-.059-1.69-.073-4.949-.073zm0 5.838c-3.403 0-6.162 2.759-6.162 6.162s2.759 6.163 6.162 6.163 6.162-2.759 6.162-6.163c0-3.403-2.759-6.162-6.162-6.162zm0 10.162c-2.209 0-4-1.79-4-4 0-2.209 1.791-4 4-4s4 1.791 4 4c0 2.21-1.791 4-4 4zm6.406-11.845c-.796 0-1.441.645-1.441 1.44s.645 1.44 1.441 1.44c.795 0 1.439-.645 1.439-1.44s-.644-1.44-1.439-1.44z" />
|
||||
</svg>
|
||||
</a>
|
||||
<a
|
||||
href="https://www.youtube.com/channel/UC-VIPk6M1K4xEA-gXv6_cZQ"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="group p-3 bg-gradient-to-r from-red-600 to-red-700 text-white rounded-xl shadow-md hover:shadow-lg transition-all duration-200 transform hover:scale-110"
|
||||
>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" className="h-5 w-5" fill="currentColor" viewBox="0 0 24 24">
|
||||
<path d="M19.615 3.184c-3.604-.246-11.631-.245-15.23 0-3.897.266-4.356 2.62-4.385 8.816.029 6.185.484 8.549 4.385 8.816 3.6.245 11.626.246 15.23 0 3.897-.266 4.356-2.62 4.385-8.816-.029-6.185-.484-8.549-4.385-8.816zm-10.615 12.816v-8l8 3.993-8 4.007z" />
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Footer Bottom */}
|
||||
<div className="pt-8 border-t border-ccfw-teal/20">
|
||||
<div className="flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0">
|
||||
<div className="text-center md:text-left">
|
||||
<p className="text-ccfw-maroon font-medium">
|
||||
© 2024 Cape Coral Friends of Wildlife. All rights reserved.
|
||||
</p>
|
||||
<p className="text-xs text-ccfw-maroon mt-1">
|
||||
Made with ❤️ for Florida's wildlife
|
||||
</p>
|
||||
</div>
|
||||
<div className="flex items-center space-x-6 text-xs text-ccfw-maroon font-medium">
|
||||
<span>Privacy Policy</span>
|
||||
<span>Terms of Service</span>
|
||||
<span>Accessibility</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</footer>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -52,4 +52,28 @@ const CardContent = React.forwardRef<
|
||||
))
|
||||
CardContent.displayName = "CardContent"
|
||||
|
||||
export { Card, CardHeader, CardTitle, CardContent }
|
||||
const CardDescription = React.forwardRef<
|
||||
HTMLParagraphElement,
|
||||
React.HTMLAttributes<HTMLParagraphElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<p
|
||||
ref={ref}
|
||||
className={cn("text-sm text-muted-foreground", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardDescription.displayName = "CardDescription"
|
||||
|
||||
const CardFooter = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.HTMLAttributes<HTMLDivElement>
|
||||
>(({ className, ...props }, ref) => (
|
||||
<div
|
||||
ref={ref}
|
||||
className={cn("flex items-center p-6 pt-0", className)}
|
||||
{...props}
|
||||
/>
|
||||
))
|
||||
CardFooter.displayName = "CardFooter"
|
||||
|
||||
export { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter }
|
||||
|
||||
@ -14,12 +14,12 @@ services:
|
||||
- ${DEV_PORT_2:-5000}:5000
|
||||
- 9229:9229
|
||||
volumes:
|
||||
- ../:/app:cached
|
||||
- .:/app:cached
|
||||
- node_modules:/app/node_modules
|
||||
- npm-cache:/root/.npm
|
||||
- ~/.gitconfig:/root/.gitconfig
|
||||
- ~/.ssh:/root/.ssh
|
||||
version: '3.8'
|
||||
|
||||
volumes:
|
||||
node_modules: {}
|
||||
npm-cache: {}
|
||||
|
||||
BIN
images/CCFW_screenshot1.JPG
Normal file
BIN
images/CCFW_screenshot1.JPG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 173 KiB |
BIN
images/CCFW_screenshot2.JPG
Normal file
BIN
images/CCFW_screenshot2.JPG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 144 KiB |
BIN
images/CCFW_screenshot3.JPG
Normal file
BIN
images/CCFW_screenshot3.JPG
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
# Python dependencies for development
|
||||
# This project is primarily a Next.js application
|
||||
# Add any Python dependencies here if needed
|
||||
@ -10,8 +10,27 @@ module.exports = {
|
||||
colors: {
|
||||
background: 'rgb(var(--background) / <alpha-value>)',
|
||||
foreground: 'rgb(var(--foreground) / <alpha-value>)',
|
||||
muted: 'rgb(var(--muted) / <alpha-value>)',
|
||||
'muted-foreground': 'rgb(var(--muted-foreground) / <alpha-value>)',
|
||||
accent: 'rgb(var(--accent) / <alpha-value>)',
|
||||
'accent-foreground': 'rgb(var(--accent-foreground) / <alpha-value>)',
|
||||
card: 'rgb(var(--card) / <alpha-value>)',
|
||||
'card-foreground': 'rgb(var(--card-foreground) / <alpha-value>)',
|
||||
primary: 'rgb(var(--primary) / <alpha-value>)',
|
||||
'primary-foreground': 'rgb(var(--primary-foreground) / <alpha-value>)',
|
||||
secondary: 'rgb(var(--secondary) / <alpha-value>)',
|
||||
'secondary-foreground': 'rgb(var(--secondary-foreground) / <alpha-value>)',
|
||||
destructive: 'rgb(var(--destructive) / <alpha-value>)',
|
||||
'destructive-foreground': 'rgb(var(--destructive-foreground) / <alpha-value>)',
|
||||
border: 'rgb(var(--border) / <alpha-value>)',
|
||||
input: 'rgb(var(--input) / <alpha-value>)',
|
||||
ring: 'rgb(var(--ring) / <alpha-value>)',
|
||||
// CCFW specific colors
|
||||
'ccfw-gold': 'rgb(var(--ccfw-gold) / <alpha-value>)',
|
||||
'ccfw-teal': 'rgb(var(--ccfw-teal) / <alpha-value>)',
|
||||
'ccfw-coral': 'rgb(var(--ccfw-coral) / <alpha-value>)',
|
||||
'ccfw-beige': 'rgb(var(--ccfw-beige) / <alpha-value>)',
|
||||
'ccfw-maroon': 'rgb(var(--ccfw-maroon) / <alpha-value>)',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@ -1,14 +0,0 @@
|
||||
# ~/.ssh/config entry for Gitea
|
||||
Host gitea
|
||||
HostName localhost
|
||||
Port 222
|
||||
User git
|
||||
IdentityFile ~/.ssh/id_ed25519 # Or whatever your SSH key is
|
||||
PreferredAuthentications publickey
|
||||
|
||||
Host localhost
|
||||
HostName localhost
|
||||
Port 222
|
||||
User git
|
||||
IdentityFile ~/.ssh/id_ed25519
|
||||
PreferredAuthentications publickey
|
||||
Loading…
x
Reference in New Issue
Block a user