← back to Jill Website

src/models/PageContent.ts

203 lines

import { getPool } from '../config/database';

export interface PageContent {
  id?: number;
  page_slug: string;
  page_title: string;
  content: string;
  gallery_images: string[];
  created_at?: Date;
  updated_at?: Date;
}

export class PageContentModel {
  private pool = getPool();

  /**
   * Validate page content data
   */
  private validate(pageContent: Partial<PageContent>): void {
    const errors: string[] = [];

    if (!pageContent.page_slug || pageContent.page_slug.trim().length === 0) {
      errors.push('Page slug is required');
    }

    if (!pageContent.page_title || pageContent.page_title.trim().length === 0) {
      errors.push('Page title is required');
    }

    if (!pageContent.content || pageContent.content.trim().length === 0) {
      errors.push('Content is required');
    }

    if (errors.length > 0) {
      const errorMessage = errors.join(', ');
      throw new Error('Validation failed: ' + errorMessage);
    }
  }

  /**
   * Create new page content
   */
  async create(pageContent: Omit<PageContent, 'id' | 'created_at' | 'updated_at'>): Promise<PageContent> {
    this.validate(pageContent);

    try {
      const query = `
        INSERT INTO page_content (page_slug, page_title, content, gallery_images)
        VALUES ($1, $2, $3, $4)
        RETURNING *
      `;

      const values = [
        pageContent.page_slug.trim(),
        pageContent.page_title.trim(),
        pageContent.content.trim(),
        JSON.stringify(pageContent.gallery_images || [])
      ];

      const result = await this.pool.query(query, values);
      const row = result.rows[0];

      return {
        ...row,
        gallery_images: typeof row.gallery_images === 'string'
          ? JSON.parse(row.gallery_images)
          : row.gallery_images
      };
    } catch (error) {
      console.error('Error creating page content:', error);
      throw new Error(`Failed to create page content: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  /**
   * Find page content by ID
   */
  async findById(id: number): Promise<PageContent | null> {
    try {
      const query = 'SELECT * FROM page_content WHERE id = $1';
      const result = await this.pool.query(query, [id]);

      if (result.rows.length === 0) {
        return null;
      }

      const row = result.rows[0];
      return {
        ...row,
        gallery_images: typeof row.gallery_images === 'string'
          ? JSON.parse(row.gallery_images)
          : row.gallery_images
      };
    } catch (error) {
      console.error('Error finding page content by ID:', error);
      throw new Error(`Failed to find page content: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  /**
   * Find page content by slug
   */
  async findBySlug(slug: string): Promise<PageContent | null> {
    try {
      const query = 'SELECT * FROM page_content WHERE page_slug = $1';
      const result = await this.pool.query(query, [slug]);

      if (result.rows.length === 0) {
        return null;
      }

      const row = result.rows[0];
      return {
        ...row,
        gallery_images: typeof row.gallery_images === 'string'
          ? JSON.parse(row.gallery_images)
          : row.gallery_images
      };
    } catch (error) {
      console.error('Error finding page content by slug:', error);
      throw new Error(`Failed to find page content: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  /**
   * Find all page content
   */
  async findAll(limit: number = 100, offset: number = 0): Promise<PageContent[]> {
    try {
      const query = `
        SELECT * FROM page_content
        ORDER BY page_slug ASC
        LIMIT $1 OFFSET $2
      `;
      const result = await this.pool.query(query, [limit, offset]);

      return result.rows.map(row => ({
        ...row,
        gallery_images: typeof row.gallery_images === 'string'
          ? JSON.parse(row.gallery_images)
          : row.gallery_images
      }));
    } catch (error) {
      console.error('Error finding all page content:', error);
      throw new Error(`Failed to retrieve page content: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  /**
   * Update existing page content by slug
   */
  async update(slug: string, pageContent: Partial<PageContent>): Promise<PageContent | null> {
    this.validate(pageContent);

    try {
      const query = `
        UPDATE page_content
        SET page_title = $1, content = $2, gallery_images = $3
        WHERE page_slug = $4
        RETURNING *
      `;

      const values = [
        pageContent.page_title?.trim(),
        pageContent.content?.trim(),
        JSON.stringify(pageContent.gallery_images || []),
        slug
      ];

      const result = await this.pool.query(query, values);

      if (result.rows.length === 0) {
        return null;
      }

      const row = result.rows[0];
      return {
        ...row,
        gallery_images: typeof row.gallery_images === 'string'
          ? JSON.parse(row.gallery_images)
          : row.gallery_images
      };
    } catch (error) {
      console.error('Error updating page content:', error);
      throw new Error(`Failed to update page content: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }

  /**
   * Delete page content
   */
  async delete(id: number): Promise<boolean> {
    try {
      const query = 'DELETE FROM page_content WHERE id = $1';
      const result = await this.pool.query(query, [id]);
      return result.rowCount !== null && result.rowCount > 0;
    } catch (error) {
      console.error('Error deleting page content:', error);
      throw new Error(`Failed to delete page content: ${error instanceof Error ? error.message : 'Unknown error'}`);
    }
  }
}