Files
2026-06-11 15:05:08 +08:00

259 lines
14 KiB
HTML

{% extends "base.html" %}
{% block title %}{{ prop.title }} - NexHome{% endblock %}
{% block content %}
<div class="max-w-7xl mx-auto px-4 py-8">
<!-- Breadcrumb -->
<nav class="text-sm text-gray-500 mb-6">
<a href="/" class="hover:text-accent transition">Home</a>
<span class="mx-2">/</span>
<a href="/properties" class="hover:text-accent transition">Properties</a>
<span class="mx-2">/</span>
<a href="/properties?city={{ prop.city }}" class="hover:text-accent transition">{{ prop.city }}</a>
<span class="mx-2">/</span>
<span class="text-gray-800">{{ prop.title }}</span>
</nav>
<div class="grid grid-cols-1 lg:grid-cols-3 gap-8">
<!-- Main Content -->
<div class="lg:col-span-2 space-y-6">
<!-- Image -->
<div class="relative rounded-2xl overflow-hidden bg-gray-200 h-96">
{% if primary_image %}
<img src="/static/{{ primary_image.image_path }}"
alt="{{ prop.title }}"
class="w-full h-full object-cover">
{% else %}
<div class="flex items-center justify-center h-full text-gray-400">
<svg class="w-20 h-20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5"
d="M3 12l2-2m0 0l7-7 7 7M5 10v10a1 1 0 001 1h3m10-11l2 2m-2-2v10a1 1 0 01-1 1h-3m-4 0a1 1 0 01-1-1v-4a1 1 0 011-1h2a1 1 0 011 1v4a1 1 0 01-1 1h-2z"/>
</svg>
</div>
{% endif %}
{% if prop.is_featured %}
<span class="absolute top-4 left-4 bg-warm text-primary text-sm font-bold px-3 py-1 rounded-full">
Featured
</span>
{% endif %}
{% if prop.status == 'sold' %}
<span class="absolute top-4 right-4 bg-red-600 text-white text-sm font-bold px-3 py-1 rounded-full">
Sold
</span>
{% elif prop.status == 'pending' %}
<span class="absolute top-4 right-4 bg-yellow-500 text-white text-sm font-bold px-3 py-1 rounded-full">
Pending
</span>
{% endif %}
<!-- Floating favorite heart (top-right) -->
{% if user %}
<form method="POST" action="/properties/{{ prop.id }}/favorite" class="absolute top-4 right-4 {% if prop.status == 'sold' or prop.status == 'pending' %}top-14{% endif %}">
<button type="submit"
class="w-12 h-12 rounded-full flex items-center justify-center shadow-lg transition
{% if is_favorited %}
bg-red-500 text-white hover:bg-red-600
{% else %}
bg-white/90 text-gray-600 hover:bg-white hover:text-red-500
{% endif %}">
<svg class="w-6 h-6" fill="{% if is_favorited %}currentColor{% else %}none{% endif %}" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
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>
</form>
{% endif %}
</div>
<!-- Thumbnail gallery -->
{% if images|length > 1 %}
<div class="flex gap-2 overflow-x-auto pb-2">
{% for img in images %}
<img src="/static/{{ img.image_path }}"
alt="Property image {{ loop.index }}"
class="h-20 w-28 object-cover rounded-lg flex-shrink-0 border-2 {% if img.is_primary %}border-accent{% else %}border-transparent{% endif %}">
{% endfor %}
</div>
{% endif %}
<!-- Title & Price -->
<div>
<div class="flex items-center justify-between flex-wrap gap-4">
<h1 class="text-3xl font-bold text-primary">{{ prop.title }}</h1>
<span class="text-3xl font-extrabold text-accent">${{ "{:,}".format(prop.price) }}</span>
</div>
<p class="flex items-center text-gray-500 mt-2">
<svg class="w-5 h-5 mr-1.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M17.657 16.657L13.414 20.9a1.998 1.998 0 01-2.827 0l-4.244-4.243a8 8 0 1111.314 0z"/>
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 11a3 3 0 11-6 0 3 3 0 016 0z"/>
</svg>
{{ prop.address }}, {{ prop.city }}, {{ prop.state }} {{ prop.zip_code }}
</p>
</div>
<!-- Key Stats -->
<div class="grid grid-cols-3 gap-4 bg-white rounded-xl p-6 shadow-sm">
<div class="text-center">
<div class="text-2xl font-bold text-primary">{{ prop.bedrooms }}</div>
<div class="text-sm text-gray-500">Bedrooms</div>
</div>
<div class="text-center border-x">
<div class="text-2xl font-bold text-primary">{{ prop.bathrooms }}</div>
<div class="text-sm text-gray-500">Bathrooms</div>
</div>
<div class="text-center">
<div class="text-2xl font-bold text-primary">{{ "{:,}".format(prop.area_sqft) }}</div>
<div class="text-sm text-gray-500">Sq Ft</div>
</div>
</div>
<!-- Description -->
<div class="bg-white rounded-xl p-6 shadow-sm">
<h2 class="text-xl font-bold text-primary mb-4">Description</h2>
<p class="text-gray-600 leading-relaxed whitespace-pre-line">{{ prop.description }}</p>
</div>
<!-- Details -->
<div class="bg-white rounded-xl p-6 shadow-sm">
<h2 class="text-xl font-bold text-primary mb-4">Property Details</h2>
<div class="grid grid-cols-2 gap-4 text-sm">
<div class="flex justify-between py-2 border-b">
<span class="text-gray-500">Property Type</span>
<span class="font-medium text-gray-800 capitalize">{{ prop.property_type }}</span>
</div>
<div class="flex justify-between py-2 border-b">
<span class="text-gray-500">Year Built</span>
<span class="font-medium text-gray-800">{{ prop.year_built or 'N/A' }}</span>
</div>
<div class="flex justify-between py-2 border-b">
<span class="text-gray-500">Status</span>
<span class="font-medium text-gray-800 capitalize">{{ prop.status }}</span>
</div>
<div class="flex justify-between py-2 border-b">
<span class="text-gray-500">Listed</span>
<span class="font-medium text-gray-800">{{ prop.created_at.strftime("%B %d, %Y") }}</span>
</div>
</div>
</div>
</div>
<!-- Sidebar -->
<div class="space-y-6">
<!-- Contact Card -->
<div class="bg-white rounded-xl p-6 shadow-sm border-2 border-accent/20">
<h3 class="font-bold text-primary mb-4 text-lg">Contact Seller</h3>
<!-- Favorite button - large and prominent -->
{% if user %}
<form method="POST" action="/properties/{{ prop.id }}/favorite" class="mb-4">
<button type="submit"
class="w-full py-3.5 rounded-xl font-semibold transition text-base flex items-center justify-center gap-2
{% if is_favorited %}
bg-red-50 text-red-600 border-2 border-red-300 hover:bg-red-100
{% else %}
bg-gray-50 text-gray-700 border-2 border-gray-200 hover:border-red-300 hover:text-red-500 hover:bg-red-50
{% endif %}">
<svg class="w-6 h-6" fill="{% if is_favorited %}currentColor{% else %}none{% endif %}" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
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>
{% if is_favorited %}Saved to Favorites{% else %}Add to Favorites{% endif %}
</button>
</form>
{% else %}
<a href="/auth/login"
class="block w-full text-center py-3.5 rounded-xl font-semibold transition text-base bg-accent hover:bg-blue-700 text-white mb-4">
Login to Save
</a>
{% endif %}
<!-- Contact info -->
<div class="space-y-3">
{% if prop.contact_email %}
<a href="mailto:{{ prop.contact_email }}"
class="flex items-center gap-3 p-3 bg-gray-50 rounded-lg hover:bg-accent/5 transition group">
<div class="w-10 h-10 bg-accent/10 rounded-full flex items-center justify-center flex-shrink-0 group-hover:bg-accent/20 transition">
<svg class="w-5 h-5 text-accent" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="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>
<div class="min-w-0">
<div class="text-xs text-gray-500">Email</div>
<div class="text-sm font-medium text-gray-800 truncate">{{ prop.contact_email }}</div>
</div>
</a>
{% endif %}
{% if prop.contact_phone %}
<a href="tel:{{ prop.contact_phone }}"
class="flex items-center gap-3 p-3 bg-gray-50 rounded-lg hover:bg-accent/5 transition group">
<div class="w-10 h-10 bg-green-100 rounded-full flex items-center justify-center flex-shrink-0 group-hover:bg-green-200 transition">
<svg class="w-5 h-5 text-green-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="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 class="min-w-0">
<div class="text-xs text-gray-500">Phone</div>
<div class="text-sm font-medium text-gray-800">{{ prop.contact_phone }}</div>
</div>
</a>
{% endif %}
{% if not prop.contact_email and not prop.contact_phone %}
<!-- Fallback to owner info -->
<div class="flex items-center gap-3 p-3 bg-gray-50 rounded-lg">
<div class="w-12 h-12 bg-primary rounded-full flex items-center justify-center text-white font-bold text-lg flex-shrink-0">
{{ prop.owner.username[0]|upper }}
</div>
<div class="min-w-0">
<div class="font-semibold text-gray-800">{{ prop.owner.username }}</div>
{% if prop.owner.full_name %}
<div class="text-sm text-gray-500">{{ prop.owner.full_name }}</div>
{% endif %}
</div>
</div>
{% endif %}
</div>
{% if user.id == prop.owner_id %}
<div class="mt-4 pt-4 border-t space-y-2">
<a href="/properties/{{ prop.id }}/edit"
class="block w-full text-center py-2.5 bg-accent hover:bg-blue-700 text-white rounded-lg font-medium transition text-sm">
Edit Listing
</a>
<form method="POST" action="/properties/{{ prop.id }}/delete"
onsubmit="return confirm('Are you sure you want to delete this listing?')">
<button type="submit"
class="w-full py-2.5 bg-red-50 hover:bg-red-100 text-red-600 border border-red-200 rounded-lg font-medium transition text-sm">
Delete Listing
</button>
</form>
</div>
{% endif %}
</div>
<!-- Listed By -->
<div class="bg-white rounded-xl p-6 shadow-sm">
<h3 class="font-bold text-primary mb-4">Listed By</h3>
<div class="flex items-center space-x-3">
<div class="w-12 h-12 bg-primary rounded-full flex items-center justify-center text-white font-bold text-lg">
{{ prop.owner.username[0]|upper }}
</div>
<div>
<div class="font-semibold text-gray-800">{{ prop.owner.username }}</div>
{% if prop.owner.full_name %}
<div class="text-sm text-gray-500">{{ prop.owner.full_name }}</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</div>
{% endblock %}