All files / web/src/app/create/calendar/components CalendarPreview.tsx

0% Statements 0/114
0% Branches 0/1
0% Functions 0/1
0% Lines 0/114

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115                                                                                                                                                                                                                                     
'use client'

import { useQuery } from '@tanstack/react-query'
import { useTranslations } from 'next-intl'
import { css } from '../../../../../styled-system/css'

interface CalendarPreviewProps {
  month: number
  year: number
  format: 'monthly' | 'daily'
  previewSvg: string | null
}

async function fetchTypstPreview(
  month: number,
  year: number,
  format: string
): Promise<string | null> {
  const response = await fetch('/api/create/calendar/preview', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ month, year, format }),
  })

  if (!response.ok) {
    const errorData = await response.json().catch(() => ({}))
    throw new Error(errorData.error || errorData.message || 'Failed to fetch preview')
  }

  const data = await response.json()
  return data.svg
}

export function CalendarPreview({ month, year, format, previewSvg }: CalendarPreviewProps) {
  const t = useTranslations('calendar')
  // Use React Query to fetch Typst-generated preview (client-side only)
  const { data: typstPreviewSvg, isLoading } = useQuery({
    queryKey: ['calendar-typst-preview', month, year, format],
    queryFn: () => fetchTypstPreview(month, year, format),
    enabled: typeof window !== 'undefined', // Run on client for both formats
  })

  // Use generated PDF SVG if available, otherwise use Typst live preview
  const displaySvg = previewSvg || typstPreviewSvg

  // Show loading state while fetching preview
  if (isLoading || !displaySvg) {
    return (
      <div
        data-component="calendar-preview"
        className={css({
          bg: 'gray.800',
          borderRadius: '12px',
          padding: '2rem',
          display: 'flex',
          flexDirection: 'column',
          alignItems: 'center',
          justifyContent: 'center',
          minHeight: '600px',
        })}
      >
        <p
          className={css({
            fontSize: '1.25rem',
            color: 'gray.400',
            textAlign: 'center',
          })}
        >
          {isLoading ? t('preview.loading') : t('preview.noPreview')}
        </p>
      </div>
    )
  }

  return (
    <div
      data-component="calendar-preview"
      className={css({
        bg: 'gray.800',
        borderRadius: '12px',
        padding: '2rem',
        display: 'flex',
        flexDirection: 'column',
        alignItems: 'center',
      })}
    >
      <p
        className={css({
          fontSize: '1.125rem',
          color: 'yellow.400',
          marginBottom: '1rem',
          textAlign: 'center',
          fontWeight: 'bold',
        })}
      >
        {previewSvg
          ? t('preview.generatedPdf')
          : format === 'daily'
            ? t('preview.livePreviewFirstDay')
            : t('preview.livePreview')}
      </p>
      <div
        className={css({
          bg: 'white',
          borderRadius: '8px',
          padding: '1rem',
          maxWidth: '100%',
          overflow: 'auto',
        })}
        dangerouslySetInnerHTML={{ __html: displaySvg }}
      />
    </div>
  )
}