Files
Hotel-Booking/Backend/src/routes/page_content_routes.py
Iliyan Angelov ab832f851b updates
2025-11-18 18:35:46 +02:00

414 lines
16 KiB
Python

from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from typing import Optional
from datetime import datetime
import json
from ..config.database import get_db
from ..middleware.auth import get_current_user, authorize_roles
from ..models.user import User
from ..models.page_content import PageContent, PageType
router = APIRouter(prefix="/page-content", tags=["page-content"])
@router.get("/")
async def get_all_page_contents(
db: Session = Depends(get_db)
):
"""Get all page contents"""
try:
contents = db.query(PageContent).all()
result = []
for content in contents:
content_dict = {
"id": content.id,
"page_type": content.page_type.value,
"title": content.title,
"subtitle": content.subtitle,
"description": content.description,
"content": content.content,
"meta_title": content.meta_title,
"meta_description": content.meta_description,
"meta_keywords": content.meta_keywords,
"og_title": content.og_title,
"og_description": content.og_description,
"og_image": content.og_image,
"canonical_url": content.canonical_url,
"contact_info": json.loads(content.contact_info) if content.contact_info else None,
"map_url": content.map_url,
"social_links": json.loads(content.social_links) if content.social_links else None,
"footer_links": json.loads(content.footer_links) if content.footer_links else None,
"hero_title": content.hero_title,
"hero_subtitle": content.hero_subtitle,
"hero_image": content.hero_image,
"story_content": content.story_content,
"values": json.loads(content.values) if content.values else None,
"features": json.loads(content.features) if content.features else None,
"is_active": content.is_active,
"created_at": content.created_at.isoformat() if content.created_at else None,
"updated_at": content.updated_at.isoformat() if content.updated_at else None,
}
result.append(content_dict)
return {
"status": "success",
"data": {
"page_contents": result
}
}
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Error fetching page contents: {str(e)}"
)
@router.get("/{page_type}")
async def get_page_content(
page_type: PageType,
db: Session = Depends(get_db)
):
"""Get content for a specific page"""
try:
content = db.query(PageContent).filter(PageContent.page_type == page_type).first()
if not content:
# Return default structure if not found
return {
"status": "success",
"data": {
"page_content": None
}
}
content_dict = {
"id": content.id,
"page_type": content.page_type.value,
"title": content.title,
"subtitle": content.subtitle,
"description": content.description,
"content": content.content,
"meta_title": content.meta_title,
"meta_description": content.meta_description,
"meta_keywords": content.meta_keywords,
"og_title": content.og_title,
"og_description": content.og_description,
"og_image": content.og_image,
"canonical_url": content.canonical_url,
"contact_info": json.loads(content.contact_info) if content.contact_info else None,
"social_links": json.loads(content.social_links) if content.social_links else None,
"footer_links": json.loads(content.footer_links) if content.footer_links else None,
"hero_title": content.hero_title,
"hero_subtitle": content.hero_subtitle,
"hero_image": content.hero_image,
"story_content": content.story_content,
"values": json.loads(content.values) if content.values else None,
"features": json.loads(content.features) if content.features else None,
"is_active": content.is_active,
"created_at": content.created_at.isoformat() if content.created_at else None,
"updated_at": content.updated_at.isoformat() if content.updated_at else None,
}
return {
"status": "success",
"data": {
"page_content": content_dict
}
}
except Exception as e:
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Error fetching page content: {str(e)}"
)
@router.post("/{page_type}")
async def create_or_update_page_content(
page_type: PageType,
title: Optional[str] = None,
subtitle: Optional[str] = None,
description: Optional[str] = None,
content: Optional[str] = None,
meta_title: Optional[str] = None,
meta_description: Optional[str] = None,
meta_keywords: Optional[str] = None,
og_title: Optional[str] = None,
og_description: Optional[str] = None,
og_image: Optional[str] = None,
canonical_url: Optional[str] = None,
contact_info: Optional[str] = None,
map_url: Optional[str] = None,
social_links: Optional[str] = None,
footer_links: Optional[str] = None,
hero_title: Optional[str] = None,
hero_subtitle: Optional[str] = None,
hero_image: Optional[str] = None,
story_content: Optional[str] = None,
values: Optional[str] = None,
features: Optional[str] = None,
is_active: bool = True,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Create or update page content (admin only)"""
try:
authorize_roles(current_user, ["admin"])
# Validate JSON fields if provided
if contact_info:
try:
json.loads(contact_info)
except json.JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid JSON in contact_info"
)
if social_links:
try:
json.loads(social_links)
except json.JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid JSON in social_links"
)
if footer_links:
try:
json.loads(footer_links)
except json.JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid JSON in footer_links"
)
if values:
try:
json.loads(values)
except json.JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid JSON in values"
)
if features:
try:
json.loads(features)
except json.JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Invalid JSON in features"
)
# Check if content exists
existing_content = db.query(PageContent).filter(PageContent.page_type == page_type).first()
if existing_content:
# Update existing
if title is not None:
existing_content.title = title
if subtitle is not None:
existing_content.subtitle = subtitle
if description is not None:
existing_content.description = description
if content is not None:
existing_content.content = content
if meta_title is not None:
existing_content.meta_title = meta_title
if meta_description is not None:
existing_content.meta_description = meta_description
if meta_keywords is not None:
existing_content.meta_keywords = meta_keywords
if og_title is not None:
existing_content.og_title = og_title
if og_description is not None:
existing_content.og_description = og_description
if og_image is not None:
existing_content.og_image = og_image
if canonical_url is not None:
existing_content.canonical_url = canonical_url
if contact_info is not None:
existing_content.contact_info = contact_info
if map_url is not None:
existing_content.map_url = map_url
if social_links is not None:
existing_content.social_links = social_links
if footer_links is not None:
existing_content.footer_links = footer_links
if hero_title is not None:
existing_content.hero_title = hero_title
if hero_subtitle is not None:
existing_content.hero_subtitle = hero_subtitle
if hero_image is not None:
existing_content.hero_image = hero_image
if story_content is not None:
existing_content.story_content = story_content
if values is not None:
existing_content.values = values
if features is not None:
existing_content.features = features
if is_active is not None:
existing_content.is_active = is_active
existing_content.updated_at = datetime.utcnow()
db.commit()
db.refresh(existing_content)
return {
"status": "success",
"message": "Page content updated successfully",
"data": {
"page_content": {
"id": existing_content.id,
"page_type": existing_content.page_type.value,
"title": existing_content.title,
"updated_at": existing_content.updated_at.isoformat() if existing_content.updated_at else None,
}
}
}
else:
# Create new
new_content = PageContent(
page_type=page_type,
title=title,
subtitle=subtitle,
description=description,
content=content,
meta_title=meta_title,
meta_description=meta_description,
meta_keywords=meta_keywords,
og_title=og_title,
og_description=og_description,
og_image=og_image,
canonical_url=canonical_url,
contact_info=contact_info,
map_url=map_url,
social_links=social_links,
footer_links=footer_links,
hero_title=hero_title,
hero_subtitle=hero_subtitle,
hero_image=hero_image,
story_content=story_content,
values=values,
features=features,
is_active=is_active,
)
db.add(new_content)
db.commit()
db.refresh(new_content)
return {
"status": "success",
"message": "Page content created successfully",
"data": {
"page_content": {
"id": new_content.id,
"page_type": new_content.page_type.value,
"title": new_content.title,
"created_at": new_content.created_at.isoformat() if new_content.created_at else None,
}
}
}
except HTTPException:
raise
except Exception as e:
db.rollback()
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Error saving page content: {str(e)}"
)
@router.put("/{page_type}")
async def update_page_content(
page_type: PageType,
page_data: dict,
current_user: User = Depends(get_current_user),
db: Session = Depends(get_db)
):
"""Create or update page content using JSON body (admin only)"""
try:
authorize_roles(current_user, ["admin"])
existing_content = db.query(PageContent).filter(PageContent.page_type == page_type).first()
if not existing_content:
# Create new content if it doesn't exist
existing_content = PageContent(
page_type=page_type,
is_active=True,
)
db.add(existing_content)
# Update fields from request body
for key, value in page_data.items():
if hasattr(existing_content, key):
# Handle JSON fields - convert dict/list to JSON string
if key in ["contact_info", "social_links", "footer_links", "values", "features"] and value is not None:
if isinstance(value, str):
# Already a string, validate it's valid JSON
try:
json.loads(value)
except json.JSONDecodeError:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Invalid JSON in {key}"
)
elif isinstance(value, (dict, list)):
# Convert dict/list to JSON string for storage
value = json.dumps(value)
# Skip None values to allow partial updates
if value is not None:
setattr(existing_content, key, value)
existing_content.updated_at = datetime.utcnow()
db.commit()
db.refresh(existing_content)
content_dict = {
"id": existing_content.id,
"page_type": existing_content.page_type.value,
"title": existing_content.title,
"subtitle": existing_content.subtitle,
"description": existing_content.description,
"content": existing_content.content,
"meta_title": existing_content.meta_title,
"meta_description": existing_content.meta_description,
"meta_keywords": existing_content.meta_keywords,
"og_title": existing_content.og_title,
"og_description": existing_content.og_description,
"og_image": existing_content.og_image,
"canonical_url": existing_content.canonical_url,
"contact_info": json.loads(existing_content.contact_info) if existing_content.contact_info else None,
"social_links": json.loads(existing_content.social_links) if existing_content.social_links else None,
"footer_links": json.loads(existing_content.footer_links) if existing_content.footer_links else None,
"hero_title": existing_content.hero_title,
"hero_subtitle": existing_content.hero_subtitle,
"hero_image": existing_content.hero_image,
"story_content": existing_content.story_content,
"values": json.loads(existing_content.values) if existing_content.values else None,
"features": json.loads(existing_content.features) if existing_content.features else None,
"is_active": existing_content.is_active,
"updated_at": existing_content.updated_at.isoformat() if existing_content.updated_at else None,
}
return {
"status": "success",
"message": "Page content updated successfully",
"data": {
"page_content": content_dict
}
}
except HTTPException:
raise
except Exception as e:
db.rollback()
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Error updating page content: {str(e)}"
)