readysite / website / internal / content / seed / files.go
4.8 KB
files.go
package seed

import (
	"log"

	"github.com/readysite/readysite/pkg/database"
	"github.com/readysite/readysite/website/models"
)

// Files seeds example files (logo, CSS, JS) if none exist.
func Files() {
	count := models.Files.Count("")
	if count > 0 {
		log.Printf("seed: skipping files (found %d existing files)", count)
		return
	}

	log.Println("seed: creating example files...")

	// Logo SVG
	logoSVG := `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
  <defs>
    <linearGradient id="grad" x1="0%" y1="0%" x2="100%" y2="100%">
      <stop offset="0%" style="stop-color:#6366f1"/>
      <stop offset="100%" style="stop-color:#8b5cf6"/>
    </linearGradient>
  </defs>
  <rect width="100" height="100" rx="20" fill="url(#grad)"/>
  <text x="50" y="65" font-family="system-ui, sans-serif" font-size="48" font-weight="bold" fill="white" text-anchor="middle">R</text>
</svg>`

	logoFile := &models.File{
		Model:     database.Model{ID: "logo"},
		Name:      "logo.svg",
		MimeType:  "image/svg+xml",
		Size:      int64(len(logoSVG)),
		Data:      []byte(logoSVG),
		Published: true,
		Path:      "images/logo.svg",
	}
	if _, err := models.Files.Insert(logoFile); err != nil {
		log.Printf("seed: failed to insert logo file: %v", err)
	}

	// Custom CSS
	customCSS := `/* Custom styles for your site */

/* Hero section styling */
.hero-gradient {
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
}

/* Card hover effects */
.card-hover {
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.card-hover:hover {
  transform: translateY(-2px);
  box-shadow: 0 10px 40px rgba(0, 0, 0, 0.1);
}

/* Smooth scroll */
html {
  scroll-behavior: smooth;
}

/* Focus styles for accessibility */
:focus-visible {
  outline: 2px solid #6366f1;
  outline-offset: 2px;
}

/* Animation utilities */
@keyframes fade-in {
  from { opacity: 0; transform: translateY(10px); }
  to { opacity: 1; transform: translateY(0); }
}

.animate-fade-in {
  animation: fade-in 0.3s ease-out;
}
`

	cssFile := &models.File{
		Model:     database.Model{ID: "custom-css"},
		Name:      "custom.css",
		MimeType:  "text/css",
		Size:      int64(len(customCSS)),
		Data:      []byte(customCSS),
		Published: true,
		Path:      "css/custom.css",
	}
	if _, err := models.Files.Insert(cssFile); err != nil {
		log.Printf("seed: failed to insert CSS file: %v", err)
	}

	// Custom JavaScript
	customJS := `// Custom JavaScript utilities

// Toast notification helper
function showToast(message, type = 'info') {
  const toast = document.createElement('div');
  toast.className = 'toast toast-end';
  toast.innerHTML = '<div class="alert alert-' + type + '"><span>' + message + '</span></div>';
  document.body.appendChild(toast);
  setTimeout(() => toast.remove(), 3000);
}

// Smooth scroll to element
function scrollTo(selector) {
  const el = document.querySelector(selector);
  if (el) el.scrollIntoView({ behavior: 'smooth' });
}

// Format date helper
function formatDate(date) {
  return new Intl.DateTimeFormat('en-US', {
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  }).format(new Date(date));
}

// Debounce helper for search inputs
function debounce(fn, delay = 300) {
  let timeout;
  return function(...args) {
    clearTimeout(timeout);
    timeout = setTimeout(() => fn.apply(this, args), delay);
  };
}

// Copy to clipboard
async function copyToClipboard(text) {
  try {
    await navigator.clipboard.writeText(text);
    showToast('Copied to clipboard', 'success');
  } catch (err) {
    showToast('Failed to copy', 'error');
  }
}
`

	jsFile := &models.File{
		Model:     database.Model{ID: "custom-js"},
		Name:      "custom.js",
		MimeType:  "text/javascript",
		Size:      int64(len(customJS)),
		Data:      []byte(customJS),
		Published: true,
		Path:      "js/custom.js",
	}
	if _, err := models.Files.Insert(jsFile); err != nil {
		log.Printf("seed: failed to insert JS file: %v", err)
	}

	// Placeholder image (simple SVG)
	placeholderSVG := `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 400 300" width="400" height="300">
  <rect width="400" height="300" fill="#e5e7eb"/>
  <g fill="#9ca3af">
    <rect x="170" y="110" width="60" height="50" rx="5"/>
    <circle cx="185" cy="125" r="8"/>
    <polygon points="175,155 200,130 215,145 225,135 230,155"/>
  </g>
  <text x="200" y="200" font-family="system-ui, sans-serif" font-size="14" fill="#6b7280" text-anchor="middle">400 x 300</text>
</svg>`

	placeholderFile := &models.File{
		Model:     database.Model{ID: "placeholder"},
		Name:      "placeholder.svg",
		MimeType:  "image/svg+xml",
		Size:      int64(len(placeholderSVG)),
		Data:      []byte(placeholderSVG),
		Published: true,
		Path:      "images/placeholder.svg",
	}
	if _, err := models.Files.Insert(placeholderFile); err != nil {
		log.Printf("seed: failed to insert placeholder file: %v", err)
	}

	log.Println("seed: example files created successfully")
}
← Back