diff --git a/.env.example b/.env.example index b9bb631..b4755fd 100644 --- a/.env.example +++ b/.env.example @@ -98,7 +98,8 @@ MICROSITE_API_BASE_URL=http://localhost:3001/api # Infra: wildcard DNS *.eventbuzz.live → CloudFront; map Host header to # s3://{AWS_BUCKET}/{MICROSITE_V2_S3_PREFIX}/sites/{subdomain}/index.html # Dev fallback: open published HTML via CloudFront URL of index.html key directly. -# Seed first template: npm run seed:microsite-v2-template +# Seed bundled microsite templates: npm run seed:global-microsite-v2-templates +# Or one template: npm run seed:eventify-template / npm run seed:eventre-template # # Published-site target: s3 (default) | ec2. When ec2, rendered index.html + # config.json are uploaded via SFTP to {REMOTE_ROOT}/{subdomain}/ on the EC2 box. diff --git a/microsite-v2-templates/crest-novel/assets/css/main.css b/microsite-v2-templates/crest-novel/assets/css/main.css index 7905fe7..425e004 100644 --- a/microsite-v2-templates/crest-novel/assets/css/main.css +++ b/microsite-v2-templates/crest-novel/assets/css/main.css @@ -1609,6 +1609,98 @@ h1 { font-size: 13px; } +.schedule .schedule-theme-card { + border: none; + margin-bottom: 0; + display: block; +} + +.schedule .schedule-theme-card .d-flex, +.schedule .schedule-theme-card .schedule-theme-row { + display: flex; + flex-wrap: nowrap; + align-items: stretch; +} + +.schedule .schedule-theme-name { + margin-bottom: 0; + word-break: break-word; +} + +.schedule .schedule-session-topics { + padding: 16px 32px 20px 300px; +} + +.schedule .schedule-topic { + display: grid; + grid-template-columns: 150px 96px minmax(0, 1fr) 220px; + column-gap: 16px; + align-items: start; + padding: 10px 0; + border-bottom: 1px dashed #eee; +} + +.schedule .schedule-topic:last-child { + border-bottom: none; +} + +.schedule .schedule-topic-head { + padding-top: 0; + padding-bottom: 8px; + border-bottom: 2px solid #e5e5e5; + margin-bottom: 2px; +} + +.schedule .schedule-topic-head .schedule-topic-type, +.schedule .schedule-topic-head .schedule-topic-duration, +.schedule .schedule-topic-head .schedule-topic-title, +.schedule .schedule-topic-head .schedule-topic-role { + font-size: 11px; + font-weight: 700; + text-transform: uppercase; + letter-spacing: 0.04em; + color: #888; + font-style: normal; +} + +.schedule .schedule-topic-type, +.schedule .schedule-topic-duration, +.schedule .schedule-topic-title, +.schedule .schedule-topic-role { + min-width: 0; +} + +.schedule .schedule-topic-type { + font-size: 12px; + font-weight: 600; + text-transform: uppercase; + color: var(--eventup-accent-start, #015AAA); + line-height: 1.4; +} + +.schedule .schedule-topic-duration { + font-size: 13px; + font-weight: 600; + color: #555; + line-height: 1.4; + white-space: nowrap; +} + +.schedule .schedule-topic-title { + font-size: 15px; + font-weight: 500; + color: #212121; + line-height: 1.45; +} + +.schedule .schedule-topic-role { + font-size: 13px; + color: #777; + font-style: italic; + line-height: 1.4; + text-align: right; +} + .schedule .show .card-body { background: #f3f4f3; } @@ -1616,14 +1708,17 @@ h1 { .schedule .card .schedule-slot-time { background-image: linear-gradient(65deg, var(--eventup-accent-start) 0, var(--eventup-accent-end) 100%); color: #fff; - padding: 38px 28px; + padding: 32px 16px; float: none; - font-size: 18px; + font-size: 15px; font-weight: 700; + line-height: 1.35; + white-space: nowrap; -webkit-box-flex: 0; - -ms-flex: 0 0 18%; - flex: 0 0 18%; - max-width: 18%; + -ms-flex: 0 0 26%; + flex: 0 0 26%; + min-width: 230px; + max-width: 26%; display: flex; align-items: center; justify-content: center; diff --git a/microsite-v2-templates/crest-novel/assets/css/responsive.css b/microsite-v2-templates/crest-novel/assets/css/responsive.css index 092947a..f40b3ae 100644 --- a/microsite-v2-templates/crest-novel/assets/css/responsive.css +++ b/microsite-v2-templates/crest-novel/assets/css/responsive.css @@ -15,6 +15,10 @@ .schedule .card .schedule-slot-time { padding: 38px 22px; } + .schedule .schedule-topic { + grid-template-columns: 132px 88px minmax(0, 1fr) 190px; + column-gap: 12px; + } #pricing .price-block-wrapper .pricing-list { padding: 10px 35px 10px 45px; } @@ -139,8 +143,10 @@ } .schedule .card .schedule-slot-time { font-size: 14px; - padding: 29px; - max-width: 22%; + padding: 24px 12px; + min-width: 210px; + flex: 0 0 26%; + max-width: 26%; } .schedule .schedule-tab-title .nav-tabs .nav-link { width: 150px; @@ -245,6 +251,42 @@ margin-left: 0; margin-top: 4px; } + .schedule .schedule-session-topics { + padding: 16px 20px; + } + .schedule .schedule-topic { + grid-template-columns: 108px 72px minmax(0, 1fr); + column-gap: 10px; + row-gap: 4px; + } + .schedule .schedule-topic-role { + grid-column: 1 / -1; + text-align: left; + padding-top: 2px; + } + .schedule .schedule-theme-card .schedule-theme-row { + flex-wrap: nowrap; + } + .schedule .card .schedule-slot-time { + flex: 0 0 48%; + min-width: 200px; + max-width: 48%; + padding: 14px 10px; + font-size: 12px; + white-space: nowrap; + } + .schedule .card-header.schedule-card-header-static { + flex: 1 1 auto; + width: auto; + min-width: 0; + padding: 16px 14px; + } + .schedule .card-header.schedule-card-header-static h4, + .schedule .card-header.schedule-card-header-static .schedule-theme-name { + font-size: 13px; + line-height: 1.35; + word-break: break-word; + } #information-bar .info-bar-item { margin-bottom: 24px; } @@ -298,10 +340,12 @@ } .schedule .card .schedule-slot-time { display: flex; - flex: 0 0 22%; - max-width: 22%; - font-size: 12px; - padding: 20px 12px; + flex: 0 0 48%; + min-width: 190px; + max-width: 48%; + font-size: 11px; + padding: 16px 10px; + white-space: nowrap; } .schedule .card-header { padding: 30px; diff --git a/microsite-v2-templates/crest-novel/assets/js/site-config.js b/microsite-v2-templates/crest-novel/assets/js/site-config.js index dc7678c..a442be4 100644 --- a/microsite-v2-templates/crest-novel/assets/js/site-config.js +++ b/microsite-v2-templates/crest-novel/assets/js/site-config.js @@ -1244,17 +1244,120 @@ initCounterUp(section); } - function renderScheduleSession(session) { + function inferScheduleAmPm(hour, dayIndex) { + if (dayIndex === 0 && hour >= 1 && hour <= 6) return 'PM'; + if (dayIndex >= 1) { + if (hour >= 9 && hour <= 11) return 'AM'; + if (hour === 12) return 'PM'; + } + if (hour >= 1 && hour <= 6) return 'PM'; + if (hour >= 7 && hour <= 11) return 'AM'; + if (hour === 12) return 'PM'; + return 'AM'; + } + + function formatClockPart(part, dayIndex) { + var trimmed = String(part || '').trim(); + var match = trimmed.match(/^(\d{1,2})\s*:\s*(\d{2})\s*(am|pm|a\.m|p\.m)?\.?$/i); + if (!match) return trimmed; + + var hour = parseInt(match[1], 10); + var minute = parseInt(match[2], 10); + var explicit = match[3] ? match[3].replace(/\./g, '').toLowerCase() : ''; + var suffix = explicit === 'am' || explicit === 'pm' + ? explicit.toUpperCase() + : inferScheduleAmPm(hour, dayIndex); + var hour12 = suffix === 'AM' + ? (hour === 12 ? 12 : hour) + : (hour >= 1 && hour <= 6 ? hour : (hour === 12 ? 12 : (hour > 12 ? hour - 12 : hour))); + + return hour12 + ':' + String(minute).padStart(2, '0') + ' ' + suffix; + } + + function formatScheduleTimeDisplay(timeStr, dayIndex) { + var raw = String(timeStr || '').trim(); + if (!raw) return ''; + if (/\b(am|pm|a\.m|p\.m)\b/i.test(raw)) return raw; + + var separator = /\s+to\s+/i.test(raw) ? ' to ' : ' - '; + var parts = raw.split(/\s+to\s+|\s*-\s*/i).map(function (part) { + return String(part || '').trim(); + }).filter(Boolean); + if (parts.length < 2) return raw; + + return formatClockPart(parts[0], dayIndex) + separator + formatClockPart(parts[1], dayIndex); + } + + function escapeHtml(str) { + return String(str == null ? '' : str) + .replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"'); + } + + function renderScheduleTopic(topic) { + var durationLabel = topic.duration + ? (/^\d+(\s*\+\s*\d+)?$/.test(String(topic.duration).trim()) + ? escapeHtml(topic.duration) + ' min' + : escapeHtml(topic.duration)) + : ''; + + return '
{{sections.event_highlights.subtitle}}
{{/if}} +{{this.description}}
+ 0{{@index}} +{{sections.speakers.subtitle}}
{{/if}} +{{this.role}}
+{{sections.event_schedule.subtitle}}
{{/if}} +| {{this.time}} | +{{this.type}} | +{{this.title}} | +
{{sections.sponsors.subtitle}}
{{/if}} +{{sections.contact.subtitle}}
{{/if}} +{{sections.contact.address}}
{{/if}} +