You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

764 lines
40 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

'use client'
import React, { useState, useEffect } from 'react'
import { Search, User, MapPin, Calendar, Gift, Heart, MessageCircle, Share2, Bell, Settings, TrendingUp, Users, Compass, Camera, Menu, ChevronDown, Loader2, DollarSign, Mail, Phone, Globe, Instagram, Cake, Briefcase, Languages, Plane, X, Link } from 'lucide-react'
import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input"
import { Card, CardContent, CardFooter, CardHeader } from "@/components/ui/card"
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Badge } from "@/components/ui/badge"
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
import { Progress } from "@/components/ui/progress"
import { Textarea } from "@/components/ui/textarea"
import { User as UserType } from '@/lib/userDatabase'
import { userDatabase } from '@/lib/userDatabase'
import { CarouselSection } from '@/components/CarouselSection'
import { calculateSimilarity } from '@/lib/matchingAlgorithm';
import { } from '@/components/个人资料'
export function () {
// 定义一个渐变背景样式
const gradientBackground = `
// 从左上角到右下角的渐变,颜色从浅靛蓝过渡到浅紫,最后到浅粉
bg-gradient-to-br from-indigo-200 via-purple-200 to-pink-200
// 从右下角到左上角的渐变,颜色从浅黄过渡到浅红,最后到浅粉
// bg-blend-overlay 使这个渐变与前一个渐变混合
bg-gradient-to-tl from-yellow-100 via-red-100 to-pink-100 bg-blend-overlay
// 将背景不透明度设置为50%,使其半透明
bg-opacity-50
// 应用一个动画效果,可能是使渐变在水平方向上移动
animate-gradient-x
// 确保背景至少占满整个屏幕高度
min-h-screen
// 设置文本颜色为深灰色
text-gray-800
`;
const [, set] = useState('')
const [, set] = useState('')
const [, set] = useState('')
const [isMatching, setIsMatching] = useState(false)
const [matchResult, setMatchResult] = useState<UserType | null>(null)
const [matchingProgress, setMatchingProgress] = useState(0)
const [users, setUsers] = useState<UserType[]>([])
const [selectedEvent, setSelectedEvent] = useState<string | null>(null)
const [selectedInspirationIndex, setSelectedInspirationIndex] = useState<number | null>(null)
const [showProfile, setShowProfile] = useState(false)
const [posts, setPosts] = useState([
{
id: 1,
user: '小明',
avatar: 'https://images.unsplash.com/photo-1599566150163-29194dcaad36?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=774&q=80',
location: '巴黎',
image: 'https://images.unsplash.com/photo-1499856871958-5b9627545d1a?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80',
content: '巴黎的魅力无处不在!从埃菲尔铁塔到卢浮宫,每一步都是艺术的洗礼。分享我在这座浪漫之都的精彩瞬间! #巴黎梦 #艺术之旅',
likes: 328,
comments: [],
isLiked: false
},
{
id: 2,
user: '小红',
avatar: 'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=774&q=80',
location: '东京',
image: 'https://images.unsplash.com/photo-1503899036084-c55cdd92da26?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80',
content: '东京,一座永不入睡的城市!从繁华的涉谷到宁静的浅草寺,感受这里的无限活力。分享我在东京的精彩旅程! #东京探险 #日本文化',
likes: 256,
comments: [],
isLiked: false
},
{
id: 3,
user: '小李',
avatar: 'https://images.unsplash.com/photo-1552058544-f2b08422138a?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1740&q=80',
location: '纽约',
image: 'https://images.unsplash.com/photo-1496442226666-8d4d0e62e6e9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80',
content: '纽约,梦想之城!从中央公园到百老汇,每一刻都充满可能。在这里,平凡人也能创造非凡故事。分享我的纽约冒险! #纽约生活 #追梦人生',
likes: 412,
comments: [],
isLiked: false
},
{
id: 4,
user: '小张',
avatar: 'https://images.unsplash.com/photo-1554151228-14d9def656e4?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1740&q=80',
location: '伦敦',
image: 'https://images.unsplash.com/photo-1513635269975-59663e0ac1ad?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80',
content: '伦敦,历史与现代的完美融合!从大本钟到泰特现代美术馆,每一步都是文化的碰撞。分享我在伦敦的奇妙时光! #伦敦印象 #英伦风情',
likes: 189,
comments: [],
isLiked: false
},
{
id: 5,
user: '小王',
avatar: 'https://images.unsplash.com/photo-1438761681033-6461ffad8d80?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1740&q=80',
location: '悉尼',
image: 'https://images.unsplash.com/photo-1506973035872-a4ec16b8e8d9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80',
content: '悉尼,阳光与海滩的天堂!从歌剧院到邦迪海滩,处处洋溢着欢乐。分享我在这里的阳光假期! #悉尼生活 #澳洲之美',
likes: 275,
comments: [],
isLiked: false
},
{
id: 6,
user: '小陈',
avatar: 'https://images.unsplash.com/photo-1507003211169-0a1dd7228f2d?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1740&q=80',
location: '罗马',
image: 'https://images.unsplash.com/photo-1552832230-c0197dd311b5?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80',
content: '罗马,永恒之城!从斗兽场到梵蒂冈,每一处都是历史的见证。分享我在这座古城的深度探索! #罗马假日 #意大利风情',
likes: 301,
comments: [],
isLiked: false
},
{
id: 7,
user: '小林',
avatar: 'https://images.unsplash.com/photo-1547425260-76bcadfb4f2c?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1740&q=80',
location: '巴塞罗那',
image: 'https://images.unsplash.com/photo-1583422409516-2895a77efded?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80',
content: '巴塞罗那,一座充满激情的城市!高迪的建筑让人惊叹,地中海的阳光温暖人心。分享我在这里的精彩冒险! #巴塞罗那风情 #建筑奇迹',
likes: 233,
comments: [],
isLiked: false
},
])
// 创建一个状态来存储新评论
const [newComment, setNewComment] = useState('')
// 组件挂载时,从userDatabase加载用户数据
useEffect(() => {
setUsers(userDatabase);
}, []);
// 处理盲盒匹配的函数
const = () => {
console.log('开始盲盒匹配');
// 设置匹配状态为true,开始匹配进度为0
setIsMatching(true);
setMatchingProgress(0);
// 创建一个定时器,每200毫秒增加10%的进度,直到100%
const intervalId = setInterval(() => {
setMatchingProgress(prev => {
if (prev >= 100) {
clearInterval(intervalId);
return 100;
}
return prev + 10;
});
}, 200);
// 2秒后执行实际的匹配逻辑
setTimeout(() => {
// 构造当前用户对象
const currentUser = {
budget: Number(),
destination: ,
travelDate: new Date(),
interests: ['旅行', '摄影', '美食'], // 这里应该从用户资料中获取
};
console.log('当前用户:', currentUser);
// 对所有用户进行匹配计算
const matchedUsers = users.map(user => {
const matchUser = {
...user,
budget: Number(user.budget),
destination: user.location,
travelDate: new Date(user.travelDate),
interests: user.interests || []
};
console.log('匹配用户:', matchUser);
// 计算相似度
const similarity = calculateSimilarity(currentUser, matchUser);
console.log('相似度分数:', similarity);
return { ...user, similarity };
}).sort((a, b) => b.similarity - a.similarity); // 按相似度降序排序
console.log('匹配结果:', matchedUsers);
// 设置匹配结果
if (matchedUsers.length > 0) {
setMatchResult(matchedUsers[0]);
} else {
setMatchResult(null);
}
// 结束匹配过程
setIsMatching(false);
clearInterval(intervalId);
setMatchingProgress(100);
}, 2000);
};
// 处理点赞功能的函数
const handleLike = (postId: number) => {
setPosts(posts.map(post => {
if (post.id === postId) {
return {
...post,
// 如果已经点赞,则减少点赞数;否则增加点赞数
likes: post.isLiked ? post.likes - 1 : post.likes + 1,
// 切换点赞状态
isLiked: !post.isLiked
}
}
return post
}))
}
// 处理评论功能的函数
const handleComment = (postId: number) => {
// 检查新评论是否为空(去掉首尾空格后)
if (newComment.trim()) {
// 更新帖子列表
setPosts(posts.map(post => {
// 找到要评论的帖子
if (post.id === postId) {
return {
...post,
// 将新评论添加到评论列表中
comments: [...post.comments, newComment]
}
}
// 其他帖子保持不变
return post
}))
// 清空评论输入框
setNewComment('')
}
}
// 处理分享功能的函数
const handleShare = (postId: number) => {
// 构造帖子的URL
const url = `https://yourtravelwebsite.com/post/${postId}`
// 将URL复制到剪贴板
navigator.clipboard.writeText(url).then(() => {
// 复制成功后显示提示
alert('链接已复制到剪贴板!')
})
}
const events = [
{
title: '徒步长城',
description: '体验中国最著名的古代建筑,欣赏壮丽的风景,结识志同道合的徒步爱好者。',
date: '2023年10月15日',
duration: '1天',
difficulty: '中等',
included: ['专业导游', '午餐', '往返交通'],
image: 'https://images.unsplash.com/photo-1508804185872-d7badad00f7d?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80'
},
{
title: '樱花季摄影',
description: '在美丽的樱花季节,和其他摄影爱好者一起捕捉最美的樱花景象,提升您的摄影技巧。',
date: '2024年3月20日',
duration: '半天',
difficulty: '简单',
included: ['摄影指导', '下午茶', '照片后期工作坊'],
image: 'https://images.unsplash.com/photo-1522383225653-ed111181a951?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2076&q=80'
},
{
title: '威尼斯狂欢节',
description: '参加世界闻名的威尼斯狂欢节,体验独特的面具文化和浪漫的水城氛围。',
date: '2024年2月10日',
duration: '3天',
difficulty: '简单',
included: ['面具工作坊', '狂欢节游行门票', '威尼斯特色美食品尝'],
image: 'https://images.unsplash.com/photo-1518730518541-d0f4ea9dfab9?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80'
},
{
title: '亚马逊丛林探险',
description: '深入世界最大的热带雨林,探索丰富的生物多样性,体验原始部落文化。',
date: '2023年11月5日',
duration: '5天',
difficulty: '高',
included: ['专业向导', '丛林住宿', '野生动物观察', '部落文化体验'],
image: 'https://images.unsplash.com/photo-1516426122078-c23e76319801?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80'
},
{
title: '北极光观测之旅',
description: '前往芬兰拉普兰,在极地玻璃屋中观赏神奇的北极光,体验独特的萨米文化。',
date: '2024年1月15日',
duration: '4天',
difficulty: '中等',
included: ['极光观测', '哈士奇雪橇', '冰钓体验', '萨米文化之夜'],
image: 'https://images.unsplash.com/photo-1531366936337-7c912a4589a7?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80'
},
{
title: '日本寿司制作课程',
description: '在东京学习正宗的寿司制作技巧,深入了解日本饮食文化,品尝自己亲手制作的寿司。',
date: '2023年9月25日',
duration: '1天',
difficulty: '中等',
included: ['专业寿司师指导', '所有食材和工具', '寿司午餐', '参观筑地市场'],
image: 'https://images.unsplash.com/photo-1553621042-f6e147245754?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80'
},
{
title: '马丘比丘徒步之旅',
description: '沿着古老的印加小道徒步,探索神秘的马丘比丘遗址,感受安第斯山脉的壮美。',
date: '2024年4月10日',
duration: '4天',
difficulty: '高',
included: ['专业向导', '露营装备', '餐食', '马丘比丘门票'],
image: 'https://images.unsplash.com/photo-1526392060635-9d6019884377?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80'
},
]
const inspirations = [
{
title: '原始森林探索',
description: '深入地球上最古老的原始森林,探索生物多样性的奇迹。在茂密的树冠下徒步,观察珍稀动植物,感受大自然的神奇力量。',
activities: ['丛林徒步', '野生动物观察', '生态摄影', '夜间探险'],
destinations: ['亚马逊雨林', '刚果盆地', '大兴安岭', '婆罗洲'],
image: 'https://images.unsplash.com/photo-1511497584788-876760111969?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=1920&q=80'
},
{
title: '极地冰川探险',
description: '前往地球的极端地带,探索壮观的冰川世界。体验极昼或极夜,观察北极熊和企鹅,感受冰雪世界的震撼美景。',
activities: ['冰川徒步', '北极光观测', '冰上皮划艇', '极地野生动物观察'],
destinations: ['南极半岛', '格陵兰', '斯瓦尔巴群岛', '巴塔哥尼亚冰原'],
image: 'https://images.unsplash.com/photo-1494564605686-2e931f77a8e2?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80'
},
{
title: '火山地质探索',
description: '探索地球上最活跃的火山地带,感受大自然的原始力量。观察独特的火山地貌,体验地热温泉,了解火山对生态系统的影响。',
activities: ['火山徒步', '温泉浸泡', '地质考察', '熔岩洞穴探索'],
destinations: ['夏威夷火山国家公园', '冰岛', '印度尼西亚默拉皮火山', '意大利埃特纳火山'],
image: 'https://images.unsplash.com/photo-1462332420958-a05d1e002413?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80'
},
{
title: '沙漠探险之旅',
description: '在广袤的沙漠中体验极致的宁静与壮美。欣赏绚丽的日出日落,探索神秘的绿洲,感受沙漠文化的独特魅力。',
activities: ['沙漠徒步', '骆驼骑行', '沙丘冲浪', '星空观测'],
destinations: ['撒哈拉沙漠', '纳米比亚沙漠', '戈壁沙漠', '澳大利亚辛普森沙漠'],
image: 'https://images.unsplash.com/photo-1682686580391-615b1e32be1d?ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80'
},
{
title: '海底世界探索',
description: '潜入神秘的海底世界,探索丰富多彩的海洋生态系统。观察五彩斑斓的珊瑚礁,与海洋生物亲密接触,感受海洋的魅力与重要性。',
activities: ['深潜', '浮潜', '珊瑚礁观察', '海洋生物研究'],
destinations: ['大堡礁', '帕劳', '马尔代夫', '加拉帕戈斯群岛'],
image: 'https://images.unsplash.com/photo-1682687982501-1e58ab814714?ixlib=rb-4.0.3&ixid=M3wxMjA3fDF8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2070&q=80'
},
{
title: '高山探险挑战',
description: '挑战世界上最高的山峰,体验登山的刺激与成就感。欣赏壮丽的高山景色,了解高山生态系统,感受大自然的宏伟。',
activities: ['高山攀登', '冰川徒步', '高山摄影', '野外生存训练'],
destinations: ['珠穆朗玛峰', '乞力马扎罗山', '阿空加瓜山', '勃朗峰'],
image: 'https://images.unsplash.com/photo-1464278533981-50106e6176b1?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2074&q=80'
},
{
title: '国家公园探索',
description: '探索世界著名的国家公园,感受大自然的鬼斧神工。观察多样的野生动物,徒步壮丽的山川,体验自然保护的重要性。',
activities: ['野生动物观察', '徒步旅行', '露营', '风景摄影'],
destinations: ['黄石国家公园', '塞伦盖蒂国家公园', '托斯卡纳群岛国家公园', '吉尔吉斯斯坦天山国家公园'],
image: 'https://images.unsplash.com/photo-1472396961693-142e6e269027?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2106&q=80'
}
]
return (
<div className={gradientBackground}>
<header className="bg-white shadow sticky top-0 z-50">
{showProfile && < onClose={() => setShowProfile(false)} />}
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4 flex justify-between items-center">
<div className="flex items-center space-x-4">
<h1 className="text-3xl font-bold text-primary"></h1>
<nav className="hidden md:flex space-x-4">
<Button variant="default" className="bg-black bg-opacity-50 text-white hover:bg-opacity-100"></Button>
<Button variant="default" className="bg-black bg-opacity-50 text-white hover:bg-opacity-100"></Button>
<Button variant="default" className="bg-black bg-opacity-50 text-white hover:bg-opacity-100"></Button>
<Button variant="default" className="bg-black bg-opacity-50 text-white hover:bg-opacity-100"></Button>
</nav>
</div>
<div className="flex items-center space-x-4">
<Button variant="ghost" size="icon"><Bell /></Button>
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" size="icon"><User /></Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="end">
<DropdownMenuItem onSelect={() => setShowProfile(true)}></DropdownMenuItem>
<DropdownMenuItem></DropdownMenuItem>
<DropdownMenuItem></DropdownMenuItem>
<DropdownMenuItem>退</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
<Button variant="ghost" size="icon" className="md:hidden"><Menu /></Button>
</div>
</div>
</header>
<main className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<section className="mb-12 bg-gradient-to-r from-blue-500 to-purple-600 rounded-xl p-8 text-white relative overflow-hidden">
<img
src="https://images.unsplash.com/photo-1469854523086-cc02fe5d8800?ixlib=rb-4.0.3&ixid=M3wxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8fA%3D%3D&auto=format&fit=crop&w=2021&q=80"
className="absolute inset-0 w-full h-full object-cover opacity-50"
alt="背景图片"
/>
<div className="relative z-10">
<h2 className="text-4xl font-bold mb-4"></h2>
<p className="text-xl mb-6">使</p>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4">
<Input
type="text"
placeholder="输入目的地"
value={}
onChange={(e) => set(e.target.value)}
className="bg-white text-black"
icon={<MapPin className="text-gray-400" />}
/>
<Input
type="date"
value={}
onChange={(e) => set(e.target.value)}
className="bg-white text-black"
icon={<Calendar className="text-gray-400" />}
/>
<Input
type="number"
placeholder="输入预算(元)"
value={}
onChange={(e) => set(e.target.value)}
className="bg-white text-black"
icon={<DollarSign className="text-gray-400" />}
/>
<Dialog>
<DialogTrigger asChild>
<Button className="bg-yellow-400 text-black hover:bg-yellow-300 w-full">
<Gift className="mr-2" />
</Button>
</DialogTrigger>
<DialogContent className="sm:max-w-[600px]">
<DialogHeader>
<DialogTitle></DialogTitle>
<DialogDescription>
{isMatching ? "正在为你匹配志同道合的旅伴,请稍候..." : "准备好开始新的冒险了吗?"}
</DialogDescription>
</DialogHeader>
<div className="flex justify-center items-center min-h-[400px]">
{isMatching ? (
<div className="text-center">
<Loader2 className="w-16 h-16 text-blue-500 animate-spin mx-auto mb-4" />
<Progress value={matchingProgress} className="w-64 mx-auto mb-2" />
<p>...</p>
</div>
) : matchResult ? (
<div className="w-full">
<div className="text-center mb-6">
<Avatar className="w-32 h-32 mx-auto mb-4">
<AvatarImage src={matchResult.avatar} alt={matchResult.name} />
<AvatarFallback>{matchResult.name[0]}</AvatarFallback>
</Avatar>
<h3 className="text-2xl font-semibold mb-2">{matchResult.name}, {matchResult.age}</h3>
<p className="text-gray-600 mb-2">
<MapPin className="inline-block mr-1" size={16} />
{matchResult.location}
</p>
<p className="text-gray-600 mb-4">
<DollarSign className="inline-block mr-1" size={16} />
: {matchResult.budget}
</p>
<div className="flex justify-center space-x-2 mb-4 flex-wrap">
{matchResult.interests.map((interest, index) => (
<Badge key={index} variant="secondary" className="mb-2">{interest}</Badge>
))}
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 text-sm">
<div>
<h4 className="font-semibold mb-2"></h4>
<p className="text-gray-600 mb-4">{matchResult.bio}</p>
<h4 className="font-semibold mb-2"></h4>
<p className="text-gray-600 mb-1">
<Briefcase className="inline-block mr-2" size={16} />
{matchResult.occupation}
</p>
<p className="text-gray-600 mb-4">
<Plane className="inline-block mr-2" size={16} />
{matchResult.travelStyle}
</p>
<h4 className="font-semibold mb-2"></h4>
<p className="text-gray-600 mb-4">
<Languages className="inline-block mr-2" size={16} />
{matchResult.languages.join(', ')}
</p>
</div>
<div>
<h4 className="font-semibold mb-2"></h4>
<p className="text-gray-600 mb-1">
<Mail className="inline-block mr-2" size={16} />
{matchResult.email}
</p>
<p className="text-gray-600 mb-1">
<Phone className="inline-block mr-2" size={16} />
{matchResult.phone}
</p>
<p className="text-gray-600 mb-1">
<Instagram className="inline-block mr-2" size={16} />
{matchResult.socialMedia.instagram}
</p>
<p className="text-gray-600 mb-4">
<Globe className="inline-block mr-2" size={16} />
{matchResult.socialMedia.website}
</p>
<h4 className="font-semibold mb-2"></h4>
<div className="flex flex-wrap mb-4">
{matchResult.recentTrips.map((trip, index) => (
<Badge key={index} variant="outline" className="mr-2 mb-2">{trip}</Badge>
))}
</div>
<h4 className="font-semibold mb-2"></h4>
<div className="flex flex-wrap">
{matchResult.upcomingTrips.map((trip, index) => (
<Badge key={index} variant="outline" className="mr-2 mb-2">{trip}</Badge>
))}
</div>
</div>
</div>
<div className="mt-6">
<h4 className="font-semibold mb-2"></h4>
{matchResult.reviews.map((review, index) => (
<div key={index} className="bg-gray-100 rounded-lg p-3 mb-2">
<p className="font-semibold">{review.author} <span className="text-yellow-500">{'★'.repeat(review.rating)}</span></p>
<p className="text-gray-600">{review.content}</p>
</div>
))}
</div>
</div>
) : (
<Gift className="w-24 h-24 text-yellow-400" />
)}
</div>
{!isMatching && (
<Button onClick={} disabled={isMatching || ! || ! || !} className="w-full mt-4">
{matchResult ? "重新匹配" : "开始匹配"}
</Button>
)}
</DialogContent>
</Dialog>
</div>
</div>
</section>
<CarouselSection
title="社区动态"
items={posts}
renderItem={(post) => (
<Card key={post.id}>
<CardHeader>
<div className="flex items-center space-x-4">
<Avatar>
<AvatarImage src={post.avatar} alt={`${post.user}头像`} />
<AvatarFallback>{post.user[0]}</AvatarFallback>
</Avatar>
<div>
<h3 className="font-semibold">{post.user}</h3>
<p className="text-sm text-gray-500">3</p>
</div>
</div>
</CardHeader>
<CardContent>
<p className="mb-2">{post.content}</p>
<img src={post.image} alt="旅行照片" className="w-full h-48 object-cover rounded-lg mb-2" />
<div className="flex space-x-2">
{post.content.split('#').slice(1).map((tag, index) => (
<Badge key={index} variant="secondary">#{tag.trim()}</Badge>
))}
</div>
</CardContent>
<CardFooter className="flex justify-between">
<Button variant="ghost" size="sm" onClick={() => handleLike(post.id)}>
<Heart className={`mr-2 ${post.isLiked ? 'fill-red-500 text-red-500' : ''}`} />
{post.likes}
</Button>
<Dialog>
<DialogTrigger asChild>
<Button variant="ghost" size="sm">
<MessageCircle className="mr-2" />
{post.comments.length}
</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle></DialogTitle>
</DialogHeader>
<div className="max-h-[300px] overflow-y-auto">
{post.comments.map((comment, index) => (
<div key={index} className="mb-2 p-2 bg-gray-100 rounded">
<p>{comment}</p>
</div>
))}
</div>
<div className="mt-4">
<Textarea
placeholder="添加评论..."
value={newComment}
onChange={(e) => setNewComment(e.target.value)}
/>
<Button onClick={() => handleComment(post.id)} className="mt-2">
</Button>
</div>
</DialogContent>
</Dialog>
<Button variant="ghost" size="sm" onClick={() => handleShare(post.id)}>
<Share2 className="mr-2" />
</Button>
</CardFooter>
</Card>
)}
/>
<CarouselSection
title="即将开始的旅行活动"
items={events}
renderItem={(event) => (
<Card key={event.title} className="hover:shadow-lg transition-shadow duration-300">
<CardContent className="p-0">
<img src={event.image} alt={event.title} className="w-full h-40 object-cover" />
<div className="p-4">
<h3 className="font-semibold text-lg mb-2">{event.title}</h3>
<p className="text-sm text-gray-600 mb-2">{event.date}</p>
<Dialog>
<DialogTrigger asChild>
<Button variant="outline" size="sm"></Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>{event.title}</DialogTitle>
</DialogHeader>
<div className="mt-4">
<img src={event.image} alt={event.title} className="w-full h-48 object-cover rounded-lg mb-4" />
<p className="text-gray-700 mb-2">{event.description}</p>
<p className="text-sm text-gray-600 mb-1"><strong></strong>{event.date}</p>
<p className="text-sm text-gray-600 mb-1"><strong></strong>{event.duration}</p>
<p className="text-sm text-gray-600 mb-1"><strong></strong>{event.difficulty}</p>
<h4 className="font-semibold mt-4 mb-2"></h4>
<ul className="list-disc list-inside text-sm text-gray-600">
{event.included.map((item, i) => (
<li key={i}>{item}</li>
))}
</ul>
</div>
</DialogContent>
</Dialog>
</div>
</CardContent>
</Card>
)}
/>
<CarouselSection
title="旅行灵感"
items={inspirations}
renderItem={(inspiration) => (
<Card key={inspiration.title} className="hover:shadow-lg transition-shadow duration-300">
<CardContent className="p-0">
<img src={inspiration.image} alt={inspiration.title} className="w-full h-40 object-cover" />
<div className="p-4">
<h3 className="font-semibold text-lg mb-2">{inspiration.title}</h3>
<p className="text-sm text-gray-600 mb-2">{inspiration.description.substring(0, 100)}...</p>
<Dialog>
<DialogTrigger asChild>
<Button variant="outline" size="sm"></Button>
</DialogTrigger>
<DialogContent className="max-w-3xl">
<DialogHeader>
<DialogTitle>{inspiration.title}</DialogTitle>
</DialogHeader>
<div className="mt-4">
<img src={inspiration.image} alt={inspiration.title} className="w-full h-64 object-cover rounded-lg mb-4" />
<p className="text-gray-700 mb-4">{inspiration.description}</p>
<div className="grid grid-cols-2 gap-4">
<div>
<h4 className="font-semibold mb-2"></h4>
<ul className="list-disc list-inside text-sm text-gray-600">
{inspiration.activities.map((activity, i) => (
<li key={i}>{activity}</li>
))}
</ul>
</div>
<div>
<h4 className="font-semibold mb-2"></h4>
<ul className="list-disc list-inside text-sm text-gray-600">
{inspiration.destinations.map((destination, i) => (
<li key={i}>{destination}</li>
))}
</ul>
</div>
</div>
</div>
</DialogContent>
</Dialog>
</div>
</CardContent>
</Card>
)}
/>
<section>
<h2 className="text-2xl font-semibold mb-4 text-black"></h2>
<div className="bg-white p-6 rounded-lg shadow">
<ul className="list-disc list-inside space-y-2 text-black">
<li></li>
<li></li>
<li>便</li>
<li>使App</li>
<li></li>
<li></li>
</ul>
</div>
</section>
</main>
<footer className="bg-gray-800 text-white mt-12">
<div className="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
<div className="grid grid-cols-1 md:grid-cols-4 gap-8">
<div>
<h3 className="text-lg font-semibold mb-4"></h3>
<p className="text-sm"></p>
</div>
<div>
<h3 className="text-lg font-semibold mb-4"></h3>
<ul className="space-y-2">
<li><a href="#" className="text-sm hover:underline">使</a></li>
<li><a href="#" className="text-sm hover:underline"></a></li>
<li><a href="#" className="text-sm hover:underline"></a></li>
<li><a href="#" className="text-sm hover:underline"></a></li>
</ul>
</div>
<div>
<h3 className="text-lg font-semibold mb-4"></h3>
<div className="flex space-x-4">
<a href="#" className="text-white hover:text-gray-300"><svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path fillRule="evenodd" d="M22 12c0-5.523-4.477-10-10-10S2 6.477 2 12c0 4.991 3.657 9.128 8.438 9.878v-6.987h-2.54V12h2.54V9.797c0-2.506 1.492-3.89 3.777-3.89 1.094 0 2.238.195 2.238.195v2.46h-1.26c-1.243 0-1.63.771-1.63 1.562V12h2.773l-.443 2.89h-2.33v6.988C18.343 21.128 22 16.991 22 12z" clipRule="evenodd" /></svg></a>
<a href="#" className="text-white hover:text-gray-300"><svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path fillRule="evenodd" d="M12.315 2c2.43 0 2.784.013 3.808.06 1.064.049 1.791.218 2.427.465a4.902 4.902 0 011.772 1.153 4.902 4.902 0 011.153 1.772c.247.636.416 1.363.465 2.427.048 1.067.06 1.407.06 4.123v.08c0 2.643-.012 2.987-.06 4.043-.049 1.064-.218 1.791-.465 2.427a4.902 4.902 0 01-1.153 1.772 4.902 4.902 0 01-1.772 1.153c-.636.247-1.363.416-2.427.465-1.067.048-1.407.06-4.123.06h-.08c-2.643 0-2.987-.012-4.043-.06-1.064-.049-1.791-.218-2.427-.465a4.902 4.902 0 01-1.772-1.153 4.902 4.902 0 01-1.153-1.772c-.247-.636-.416-1.363-.465-2.427-.047-1.024-.06-1.379-.06-3.808v-.63c0-2.43.013-2.784.06-3.808.049-1.064.218-1.791.465-2.427a4.902 4.902 0 011.153-1.772A4.902 4.902 0 015.45 2.525c.636-.247 1.363-.416 2.427-.465C8.901 2.013 9.256 2 11.685 2h.63zm-.081 1.802h-.468c-2.456 0-2.784.011-3.807.058-.975.045-1.504.207-1.857.344-.467.182-.8.398-1.15.748-.35.35-.566.683-.748 1.15-.137.353-.3.882-.344 1.857-.047 1.023-.058 1.351-.058 3.807v.468c0 2.456.011 2.784.058 3.807.045.975.207 1.504.344 1.857.182.466.399.8.748 1.15.35.35.683.566 1.15.748.353.137.882.3 1.857.344 1.054.048 1.37.058 4.041.058h.08c2.597 0 2.917-.01 3.96-.058.976-.045 1.505-.207 1.858-.344.466-.182.8-.398 1.15-.748.35-.35.566-.683.748-1.15.137-.353.3-.882.344-1.857.048-1.055.058-1.37.058-4.041v-.08c0-2.597-.01-2.917-.058-3.96-.045-.976-.207-1.505-.344-1.858a3.097 3.097 0 00-.748-1.15 3.098 3.098 0 00-1.15-.748c-.353-.137-.882-.3-1.857-.344-1.023-.047-1.351-.058-3.807-.058zM12 6.865a5.135 5.135 0 110 10.27 5.135 5.135 0 010-10.27zm0 1.802a3.333 3.333 0 100 6.666 3.333 3.333 0 000-6.666zm5.338-3.205a1.2 1.2 0 110 2.4 1.2 1.2 0 010-2.4z" clipRule="evenodd" /></svg></a>
<a href="#" className="text-white hover:text-gray-300"><svg className="w-6 h-6" fill="currentColor" viewBox="0 0 24 24" aria-hidden="true"><path d="M8.29 20.251c7.547 0 11.675-6.253 11.675-11.675 0-.178 0-.355-.012-.53A8.348 8.348 0 0022 5.92a8.19 8.19 0 01-2.357.646 4.118 4.118 0 001.804-2.27 8.224 8.224 0 01-2.605.996 4.107 4.107 0 00-6.993 3.743 11.65 11.65 0 01-8.457-4.287 4.106 4.106 0 001.27 5.477A4.072 4.072 0 012.8 9.713v.052a4.105 4.105 0 003.292 4.022 4.095 4.095 0 01-1.853.07 4.108 4.108 0 003.834 2.85A8.233 8.233 0 012 18.407a11.616 11.616 0 006.29 1.84" /></svg></a>
</div>
</div>
<div>
<h3 className="text-lg font-semibold mb-4"></h3>
<p className="text-sm mb-2"></p>
<form className="flex">
<Input type="email" placeholder="您的邮箱" className="rounded-r-none" />
<Button type="submit" className="rounded-l-none"></Button>
</form>
</div>
</div>
<div className="mt-8 pt-8 border-t border-gray-700 text-center">
<p className="text-sm">&copy; 2023 . </p>
</div>
</div>
</footer>
</div>
)
}