Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions amplify/data/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { apiKeyManager } from '../functions/LambdaEncryptKeys/resource'
import { getStoreProducts } from '../functions/getStoreProducts/resource'
import { getStoreData } from '../functions/getStoreData/resource'
import { getStoreCollections } from '../functions/getStoreCollections/resource'
import { createStoreTemplate } from '../functions/createStoreTemplate/resource'

export const MODEL_ID = 'us.anthropic.claude-3-haiku-20240307-v1:0'

Expand Down Expand Up @@ -62,6 +63,16 @@ const schema = a
.authorization(allow => [allow.publicApiKey()])
.handler(a.handler.function(generatePriceSuggestionFunction)),

initializeStoreTemplate: a
.mutation()
.arguments({
storeId: a.string().required(),
domain: a.string().required(),
})
.returns(a.json())
.authorization(allow => [allow.authenticated()])
.handler(a.handler.function(createStoreTemplate)),

UserProfile: a
.model({
email: a.string(),
Expand Down Expand Up @@ -196,6 +207,7 @@ const schema = a
allow.resource(getStoreProducts),
allow.resource(getStoreData),
allow.resource(getStoreCollections),
allow.resource(createStoreTemplate),
])

export type Schema = ClientSchema<typeof schema>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
[
{
"title": "Todos los productos",
"description": "Nuestra colección completa de productos disponibles",
"slug": "todos-los-productos",
"isActive": true,
"sortOrder": 1
},
{
"title": "Productos destacados",
"description": "Nuestros productos más populares y recomendados",
"slug": "productos-destacados",
"isActive": true,
"sortOrder": 2
},
{
"title": "Ofertas especiales",
"description": "Productos con descuentos y ofertas por tiempo limitado",
"slug": "ofertas-especiales",
"isActive": true,
"sortOrder": 3
},
{
"title": "Nuevos productos",
"description": "Los últimos productos agregados a nuestra tienda",
"slug": "nuevos-productos",
"isActive": true,
"sortOrder": 4
}
]
156 changes: 156 additions & 0 deletions amplify/functions/createStoreTemplate/config/defaultSections.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
{
"header": {
"type": "header",
"settings": {
"logo": "",
"logo_width": 120,
"logo_height": 40,
"menu_title": "Menú Principal",
"show_search": true,
"show_cart": true,
"show_wishlist": false,
"show_account": true,
"sticky_header": true,
"background_color": "#ffffff",
"text_color": "#1f2937",
"border_bottom": true,
"search_placeholder": "Buscar productos...",
"cart_type": "drawer",
"menu_items": [
{ "title": "Inicio", "url": "/", "active": true },
{ "title": "Productos", "url": "/productos", "active": true },
{ "title": "Colecciones", "url": "/colecciones", "active": true },
{ "title": "Sobre nosotros", "url": "/sobre-nosotros", "active": true },
{ "title": "Contacto", "url": "/contacto", "active": true }
]
}
},

"hero": {
"type": "hero-banner",
"settings": {
"heading": "Bienvenido a tu tienda",
"heading_size": "large",
"subheading": "Descubre nuestros productos increíbles y ofertas especiales",
"subheading_size": "medium",
"button_text": "Ver productos",
"button_link": "/productos",
"button_style": "primary",
"button_size": "large",
"background_image": "",
"background_position": "center center",
"background_size": "cover",
"text_color": "#ffffff",
"text_alignment": "center",
"overlay_opacity": 50,
"overlay_color": "#000000",
"height": "large",
"content_width": "medium",
"enable_parallax": false,
"show_scroll_indicator": true
}
},

"featured-products": {
"type": "featured-products",
"settings": {
"heading": "Productos destacados",
"heading_alignment": "center",
"description": "Descubre nuestra selección especial de productos",
"products_to_show": 8,
"columns_desktop": 4,
"columns_tablet": 2,
"columns_mobile": 2,
"show_price": true,
"show_compare_price": true,
"show_description": true,
"show_vendor": false,
"show_rating": true,
"show_quick_view": true,
"show_add_to_cart": true,
"show_wishlist": false,
"image_ratio": "square",
"enable_slider": false,
"autoplay": false,
"autoplay_speed": 5000,
"show_navigation": true,
"show_pagination": true,
"card_style": "default",
"hover_effect": "zoom",
"spacing": "medium"
}
},

"collection-list": {
"type": "collection-list",
"settings": {
"heading": "Nuestras colecciones",
"heading_alignment": "center",
"description": "Explora nuestras diferentes categorías de productos",
"collections_to_show": 3,
"layout": "grid",
"columns_desktop": 3,
"columns_tablet": 2,
"columns_mobile": 1,
"show_image": true,
"show_description": true,
"show_product_count": true,
"image_ratio": "square",
"overlay_style": "gradient",
"overlay_opacity": 30,
"text_position": "center",
"button_style": "primary",
"hover_effect": "zoom",
"enable_slider": false,
"autoplay": false,
"spacing": "medium"
}
},

"footer": {
"type": "footer",
"settings": {
"background_color": "#1f2937",
"text_color": "#f9fafb",
"heading_color": "#ffffff",
"link_color": "#d1d5db",
"link_hover_color": "#ffffff",
"show_social_links": true,
"show_newsletter": true,
"show_payment_icons": true,
"show_store_info": true,
"newsletter_heading": "Suscríbete a nuestro newsletter",
"newsletter_description": "Recibe las últimas noticias, ofertas y actualizaciones",
"copyright_text": "© 2024 Tu tienda. Todos los derechos reservados.",

"quick_links": [
{ "title": "Inicio", "url": "/" },
{ "title": "Productos", "url": "/productos" },
{ "title": "Colecciones", "url": "/colecciones" },
{ "title": "Sobre nosotros", "url": "/sobre-nosotros" },
{ "title": "Contacto", "url": "/contacto" }
],

"info_links": [
{ "title": "Política de privacidad", "url": "/politicas/privacidad" },
{ "title": "Términos y condiciones", "url": "/politicas/terminos" },
{ "title": "Política de envíos", "url": "/politicas/envios" },
{ "title": "Devoluciones", "url": "/politicas/devoluciones" },
{ "title": "Preguntas frecuentes", "url": "/faq" }
],

"social_links": [
{ "platform": "facebook", "url": "", "active": false },
{ "platform": "instagram", "url": "", "active": false },
{ "platform": "twitter", "url": "", "active": false },
{ "platform": "youtube", "url": "", "active": false },
{ "platform": "tiktok", "url": "", "active": false }
],

"payment_icons": ["visa", "mastercard", "paypal", "amex"],

"layout": "four-columns",
"show_divider": true
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"layout": "theme",
"sections": {},
"order": ["header", "hero", "featured-products", "collection-list", "footer"]
}
76 changes: 76 additions & 0 deletions amplify/functions/createStoreTemplate/handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import type { Schema } from '../../data/resource'
import { Amplify } from 'aws-amplify'
import { generateClient } from 'aws-amplify/data'
import { getAmplifyDataClientConfig } from '@aws-amplify/backend/function/runtime'
import { env } from '$amplify/env/create-store-template'
import { InitializationResult } from './types/index'
import { validateInputs } from './services/validationService'
import { checkExistingTemplate, createStoreTemplate } from './services/templateService'
import { createDefaultCollections } from './services/collectionService'
import { buildTemplateData, validateTemplateData } from './utils/templateBuilder'

const { resourceConfig, libraryOptions } = await getAmplifyDataClientConfig(env)

Amplify.configure(resourceConfig, libraryOptions)

const client = generateClient<Schema>()

/**
* Handler principal para inicializar templates de tienda
*/
export const handler = async (event: any): Promise<InitializationResult> => {
try {
// Validar y extraer argumentos usando el servicio de validación
const { storeId, domain, userId } = validateInputs(event)

// Ejecutar inicialización
return await initializeStoreTemplate(storeId, domain, userId)
} catch (error) {
console.error('Error in createStoreTemplate handler:', error)
return {
success: false,
message: error instanceof Error ? error.message : 'Unknown error occurred',
}
}
}

/**
* Inicializa el template y datos por defecto para una tienda
*/
async function initializeStoreTemplate(
storeId: string,
domain: string,
owner: string
): Promise<InitializationResult> {
try {
// Verificar si ya existe un template usando el servicio
const existingCheck = await checkExistingTemplate(client, storeId)
if (!existingCheck.canProceed) {
return existingCheck.result!
}

// Crear template por defecto usando el builder
const templateData = buildTemplateData()

// Validar que el template generado sea válido
if (!validateTemplateData(templateData)) {
throw new Error('Generated template data is invalid')
}

const templateResult = await createStoreTemplate(client, storeId, domain, owner, templateData)

// Crear colecciones por defecto usando el servicio
const collectionIds = await createDefaultCollections(client, storeId, owner)

return {
success: true,
message: 'Store template initialized successfully',
templateId: templateResult.storeId,
templateData: templateData,
collections: collectionIds,
}
} catch (error) {
console.error('Error initializing store template:', error)
throw error
}
}
7 changes: 7 additions & 0 deletions amplify/functions/createStoreTemplate/resource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { defineFunction } from '@aws-amplify/backend'

export const createStoreTemplate = defineFunction({
timeoutSeconds: 120,
name: 'create-store-template',
entry: 'handler.ts',
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import type { Schema } from '../../../data/resource'
import { generateClient } from 'aws-amplify/data'
import { DefaultCollection } from '../types/index'
import defaultCollections from '../config/defaultCollections.json'

export const createDefaultCollections = async (
client: ReturnType<typeof generateClient<Schema>>,
storeId: string,
owner: string
): Promise<string[]> => {
try {
console.log(`Creating default collections for store: ${storeId}`)

const createdCollectionIds: string[] = []

// Crear todas las colecciones definidas en defaultCollections
for (const collectionConfig of defaultCollections as DefaultCollection[]) {
try {
const collection = await client.models.Collection.create({
storeId: storeId,
title: collectionConfig.title,
description: collectionConfig.description,
slug: collectionConfig.slug,
isActive: collectionConfig.isActive,
sortOrder: collectionConfig.sortOrder,
owner: owner,
})

if (collection.data?.id) {
createdCollectionIds.push(collection.data.id)
console.log(`Collection created: ${collectionConfig.title} (${collection.data.id})`)
}
} catch (collectionError) {
console.error(`Error creating collection ${collectionConfig.title}:`, collectionError)
// Continuamos con las demás colecciones aunque una falle
}
}

console.log(`Default collections created successfully. Total: ${createdCollectionIds.length}`)
return createdCollectionIds
} catch (error) {
console.error('Error creating default collections:', error)
// Retornamos array vacío en caso de error general
return []
}
}
Loading