diff --git a/content/data/section/schedule.json b/content/data/section/schedule.json new file mode 100644 index 0000000..0bb9cb7 --- /dev/null +++ b/content/data/section/schedule.json @@ -0,0 +1,298 @@ +[ + { + "day": "friday_21", + "sessions": [ + { + "start": "09:00", + "end": "12:00", + "duration": "3h", + "title": "Estamos trabalhando nisso.", + "speaker": { + "name": "Em breve", + "photo": "images/speakers/tba.jpg" + }, + "category": "web", + "type": "workshop" + }, + { + "start": "09:00", + "end": "12:00", + "duration": "40m", + "title": "Criando a sua primeira análise de sentimentos utilizando técnicas NLP e LLM’s ", + "speaker": { + "name": "Bernardo De Castro", + "photo": "images/speakers/bernardo-de-castro.jpg" + }, + "category": "data_science", + "type": "workshop" + }, + { + "start": "13:40", + "end": "17:40", + "duration": "3h", + "title": "Automatizando servidores do Discord com Python", + "speaker": { + "name": "João Paulo Carvalho", + "photo": "images/speakers/joao-paulo-carvalho.jpg" + }, + "category": "automation", + "type": "workshop" + }, + { + "start": "13:40", + "end": "17:40", + "duration": "3h", + "title": "Começando com FastAPI: construa sua primeira API em Python", + "speaker": { + "name": "Felipe de Morais", + "photo": "images/speakers/felipe-de-morais.jpg" + }, + "category": "web", + "type": "workshop" + } + ] + }, + { + "day": "saturday_22", + "sessions": [ + { + "start": "09:00", + "end": "09:40", + "duration": "40m", + "title": "Como programar como antigamente (blog em 30 min ou mais)", + "speaker": { + "name": "Perceu Bertoletti", + "photo": "images/speakers/perceu.jpg" + }, + "category": "web" + }, + { + "start": "09:50", + "end": "10:30", + "duration": "40m", + "title": "Testes Inteligentes: O Futuro da Qualidade com IA e Python", + "speaker": { + "name": "Gabriel Menezes", + "photo": "images/speakers/gabriel-menezes.jpg" + }, + "category": "testing" + }, + { + "start": "10:40", + "end": "10:50", + "duration": "10m", + "title": "Lightning Talks", + "category": "lightning_talks" + }, + { + "start": "11:00", + "end": "11:50", + "duration": "50m", + "type": "KEYNOTE", + "title": "Keynote de abertura", + "speaker": { + "name": "Cesar Brod", + "photo": "images/keynotes/cesar-brod.png" + }, + "category": "keynote" + }, + { + "start": "12:00", + "end": "13:30", + "duration": "1h30m", + "type": "ALMOÇO", + "title": "Almoço", + "category": "lunch" + }, + { + "start": "13:40", + "end": "14:10", + "duration": "30m", + "title": "VigIA: funcionário virtual de Antifraude com Google ADK", + "speaker": { + "name": "Cristiano Larrea", + "photo": "images/speakers/cristiano-larrea.jpg" + }, + "category": "automation" + }, + { + "start": "14:20", + "end": "15:00", + "duration": "40m", + "title": "Modernizando código legado Python com auxílio de IA", + "speaker": { + "name": "Eri Bastos", + "photo": "images/speakers/eri-bastos.jpg" + }, + "category": "ai" + }, + { + "start": "15:00", + "end": "15:10", + "duration": "10m", + "type": "LIGHTNING TALKS", + "title": "Lightning Talks", + "category": "lightning_talks" + }, + { + "start": "15:20", + "end": "15:50", + "duration": "30m", + "title": "Do Regex a LLM: Extraindo horários de cinema de páginas imprevisíveis", + "speaker": [ + { + "name": "Guilherme Garcia", + "photo": "images/speakers/guilherme-garcia.jpg" + }, + { + "name": "Nilton Pimentel", + "photo": "images/speakers/nilton-pimentel.jpg" + } + ], + "category": "ai" + }, + { + "start": "16:00", + "end": "16:30", + "duration": "30m", + "title": "Conversando com os dados da educação brasileira", + "speaker": { + "name": "Belisa Arnhold", + "photo": "images/speakers/belisa-arnhold.jpg" + }, + "category": "data_science" + }, + { + "start": "16:40", + "end": "17:30", + "duration": "50m", + "type": "KEYNOTE", + "title": "Keynote de Encerramento", + "speaker": { + "name": "Bruna Ferreira (bug_elseif)", + "photo": "images/keynotes/bruna-ferreira.png" + }, + "category": "keynote" + } + ] + }, + { + "day": "sunday_23", + "sessions": [ + { + "start": "09:00", + "end": "09:40", + "duration": "40m", + "title": "HTTP Server from scratch: criando seu próprio Gunicorn", + "speaker": { + "name": "Gian Carlo", + "photo": "images/speakers/gian-carlo.jpg" + }, + "category": "web" + }, + { + "start": "09:50", + "end": "10:30", + "duration": "40m", + "title": "Do Caos ao Código: Pensamento Computacional Aplicado à Regra de Negócio em Python", + "speaker": { + "name": "Glória Barboza", + "photo": "images/speakers/gloria-barboza.jpg" + }, + "category": "software_engineering" + }, + { + "start": "10:40", + "end": "10:50", + "duration": "10m", + "type": "LIGHTNING TALKS", + "title": "Lightning Talks", + "category": "lightning_talks" + }, + { + "start": "11:00", + "end": "11:50", + "duration": "50m", + "type": "KEYNOTE", + "title": "Keynote de abertura", + "speaker": { + "name": "Hisham Muhammad", + "photo": "images/keynotes/hisham-muhammad.png" + }, + "category": "keynote" + }, + { + "start": "12:00", + "end": "13:30", + "duration": "1h30m", + "type": "ALMOÇO", + "title": "Almoço", + "category": "lunch" + }, + { + "start": "13:40", + "end": "14:10", + "duration": "30m", + "title": "Cumbuca Dev: Fortalecendo o Open Source no Brasil", + "speaker": { + "name": "Maria Antônia Maia", + "photo": "images/speakers/maria-antonia-maia.jpg" + }, + "category": "open_source" + }, + { + "start": "14:20", + "end": "15:00", + "duration": "40m", + "title": "Nem Só de Código Vive o Dev", + "speaker": { + "name": "Douglas Medeiros", + "photo": "images/speakers/douglas-medeiros.jpg" + }, + "category": "career" + }, + { + "start": "15:00", + "end": "15:10", + "duration": "10m", + "type": "LIGHTNING TALKS", + "title": "Lightning Talks", + "category": "lightning_talks" + }, + { + "start": "15:20", + "end": "15:50", + "duration": "30m", + "title": "Abrindo Porteiras", + "speaker": { + "name": "Vilson Blanco Dauinheimer (Bwolf)", + "photo": "images/speakers/bwolf.jpg" + }, + "category": "career" + }, + { + "start": "16:00", + "end": "16:30", + "duration": "30m", + "title": "Otimize suas consultas: Evitando armadilhas comuns em ORMs Python", + "speaker": { + "name": "Rodrigo Bastos Vieira", + "photo": "images/speakers/rodrigo-bastos-vieira.jpg" + }, + "category": "database" + }, + { + "start": "16:40", + "end": "17:30", + "duration": "50m", + "type": "KEYNOTE", + "title": "Keynote de Encerramento", + "speaker": { + "name": "Felipe de Morais", + "photo": "images/keynotes/felipe-de-morais.jpg" + }, + "category": "keynote" + } + ] + } +] \ No newline at end of file diff --git a/content/data/speakers.json b/content/data/speakers.json new file mode 100644 index 0000000..5a420b3 --- /dev/null +++ b/content/data/speakers.json @@ -0,0 +1,116 @@ +{ + "speakers": [ + { + "name": "Bernardo De Castro", + "bio": "Bernardo de Castro Monteiro Franco Gomes, é estudante de Ciência da Computação na Universidade Federal de São João Del Rei - atualmente estou no 1° período, porém já possuo experiência na área de computação como professor, fui monitor de curso e professor particular em uma escola de cursos chama Infinity School.", + "photo": "iamges/speakers/perceu.jpg", + "talk_title": "Criando a sua primeira análise de sentimentos utilizando técnicas NLP e LLM’s ", + "talk_abstract": "Aprenda a criar sua primeira análise de sentimentos em texto utilizando técnicas de PLN e LLMs. O objetivo é apresentar desde os conceitos até a a aplicação prática, passando pelo pré-processamento de texto, uso de bibliotecas e integração com LLMs para classificação e interpretação de sentimentos." + }, + { + "name": "João Paulo Carvalho", + "bio": "Apaixonado por games. Entusiasta de Linux, open-source e evangelista do Python. Atualmente Engenheiro de Plataforma na Vinta Software. Participa da organização do Hackerspace Blumenau e GruPy Blumenau.", + "photo": "iamges/speakers/perceu.jpg", + "talk_title": "Automatizando servidores do Discord com Python ", + "talk_abstract": "Vamos aprender a usar a lib discord.py para criar bots poderosos para Discord. Vamos ver casos de uso bem populares como moderação, minigames, bots de música, até processamento de linguagem natural. Tudo usando as interfaces mais modernas da linguagem Python." + }, + { + "name": "Felipe de Morais🤴🏾", + "bio": "🎉 FeliPython aqui! Premiado com PSF Fellow 🏅, Community Service Award 🏆 e Dorneles Treméa 🏵️. Uso FastAPI há 1+ ano, obcecado por testes e adoro fazer a comunidade Python crescer! 🚀🐍", + "photo": "iamges/speakers/perceu.jpg", + "talk_title": "Começando com FastAPI: construa sua primeira API em Python", + "talk_abstract": "Aprenda a criar sua primeira API com FastAPI! Neste tutorial para iniciantes, você vai construir uma API REST do zero usando Python de forma prática e descomplicada. 🚀." + }, + { + "name": "Perceu Bertoletti", + "bio": "Desenvolvedor web(front e back) com Python, PHP, Javascript, CSS, HTML, etc. Desenvolvedor de automações com python.", + "photo": "iamges/speakers/perceu.jpg", + "talk_title": "Como programar como antigamente (blog em 30 min ou mais)", + "talk_abstract": "Inspirado pela famosa palestra de como fazer um blog em 30 minutos que já foi feita em diversas linguagens, vou apresentar como ainda existe espaço para desenvolvimento web clássico a ideia é usar django para desenvolver um blog rapido e como isso ainda pode e deve ser usado." + }, + { + "name": "Gabriel Menezes", + "bio": "Especialista em testes e qualidade de software, com mais de 7 anos de experiência na área. Atuo na comunidade Python e fui Big kahuna da Python norte 2023, passando pela Python Brasil 2022, Python Norte Itacoatiara 2024 e Python Brasil RJ 2024. Sou apaixonado por viagens, aviação, drones e videogames.", + "photo": "images/speakers/helder.jpg", + "talk_title": "Testes Inteligentes: O Futuro da Qualidade com IA e Python ", + "talk_abstract": "A Inteligência Artificial vem transformando os testes de software, incluindo geração automática de cenários, priorização de casos e detecção de falhas. Esta palestra aborda como empresas de software têm utilizado IA para aprimorar seus sistemas e otimizar o processo de desenvolvimento." + }, + { + "name": "Cristiano Larrea", + "bio": "Bacharel em Cientista de Dados e Inteligência Artificial pela FGV-RJ e Cientista de Dados Sênior na Globo.", + "photo": "images/speakers/cesar_brod.jpg", + "talk_title": "VigIA: funcionário virtual de Antifraude com Google ADK", + "talk_abstract": "Esta palestra irá abordar como o VigIA, agente de inteligência artificial desenvolvido com Google ADK e GCP, atua como um “funcionário digital” no time de antifraude da Globo. Serão apresentados os desafios do combate à fraude, a integração entre negócios e tecnologia, a arquitetura técnica do projeto." + }, + { + "name": "Eri Bastos", + "bio": "Eri Bastos é Gerente Sênior em Site Reliability Engineering, especialista em infraestrutura e cloud computing com mais de 25 anos de experiência em TI. Apaixonado por Python, atua remotamente no Canadá, liderando equipes globais e impulsionando inovação tecnológica.", + "photo": "images/speakers/ana_silva.jpg", + "talk_title": "Modernizando código legado Python com auxílio de IA", + "talk_abstract": "A palestra mostrará como aplicar inteligência artificial para modernizar código legado em Python. Serão apresentados desafios comuns, ferramentas de IA que apoiam refatoração e análise, além de estratégias práticas para reduzir dívidas técnicas e transformar sistemas antigos em bases modernas." + }, + { + "name": "Guilherme Garcia", + "bio": "Eu sou o Guilherme, também conhecido como guites! Trabalho com software a cerca de seis anos, e sou apaixonado por desenvolvimento web, acessibilidade e livre acesso ao conhecimento. Eu toco o projeto cinemaempoa.com.br junto com o time da cumbuca.dev, e estou feliz de participar da Python Sul :-)", + "photo": "images/speakers/lucas_ferreira.jpg", + "talk_title": "Do Regex a LLM: Extraindo horários de cinema de páginas imprevisíveis", + "talk_abstract": "Utilização de Modelos de Linguagem (LLMs) para extração de dados de um blog de cinema local em Porto Alegre que anuncia filmes e horários em posts de texto livre no Blogspot. Em vez de regex ou parsers rígidos, exploramos LLMs via APIs para criar um pipeline resiliente a mudanças de formato." + }, + { + "name": "Nilton Pimentel", + "bio": "Revisor Técnico – Django 5 for the Impatient (Packt Publishing) 📘Mentor – CumbucaDev 👨‍🏫Contribuidor Open Source 🌍", + "photo": "images/speakers/lucas_ferreira.jpg", + "talk_title": "Do Regex a LLM: Extraindo horários de cinema de páginas imprevisíveis", + "talk_abstract": "Utilização de Modelos de Linguagem (LLMs) para extração de dados de um blog de cinema local em Porto Alegre que anuncia filmes e horários em posts de texto livre no Blogspot. Em vez de regex ou parsers rígidos, exploramos LLMs via APIs para criar um pipeline resiliente a mudanças de formato." + }, + { + "name": "Belisa Arnhold", + "bio": "Backender apaixonada por dados.", + "photo": "images/speakers/lucas_ferreira.jpg", + "talk_title": "Conversando com os dados da educação brasileira", + "talk_abstract": "Todo ano, o INEP avalia a educação brasileira e disponibiliza os dados das pesquisas. Usando python e IA, vamos construir um chatbot que conversa com eles." + }, + { + "name": "Gian Carlo", + "bio": "Sou desenvolvedor python a 8 anos, de Porto Alegre e estou sempre querendo aprender um pouco mais cada dia.", + "photo": "images/speakers/tba.jpg", + "talk_title": "HTTP Server from scratch: criando seu próprio Gunicorn ", + "talk_abstract": "A ideia é mostrar na prática, com um livro coding, como construir um servidor HTTP minimalista do zero, em python. Vou explicar o que é wsgi, vou explorar diferentes estratégias de concorrência, como uso de threads e processos, criação de sockets e discutir formas básicas de monitoramento." + }, + { + "name": "Glória Barboza", + "bio": "Pós-graduada em Engenharia de Software, Data Science e IA, com MBA em Gestão Estratégica de Pessoas. Atuo há mais de oito anos na interseção entre pessoas, tecnologia e negócios [nem sempre nessa ordem]. Sou entusiasta de comunidades tech, conectando e desenvolvendo pessoas, além de compartilhar conhecimento e cultura.", + "photo": "images/speakers/tba.jpg", + "talk_title": "Do Caos ao Código: Pensamento Computacional Aplicado à Regra de Negócio em Python.", + "talk_abstract": "Como transformar regras de negócio vagas em soluções claras em Python. Exploraremos pensamento computacional, decomposição de requisitos e exemplos práticos, aproximando times técnicos e não técnicos para reduzir ruídos, retrabalhos e atrasos." + }, + { + "name": "Maria Antônia Maia", + "bio": "Cofundadora da Cumbuca Dev, empreendedora social na área de TI e entusiasta do Open Source. Teve a vida transformada pela tecnologia e hoje apoia novos talentos, acreditando no potencial do código aberto como ferramenta de inclusão e inovação. Pessoas > Tecnologia 💜", + "photo": "images/speakers/tba.jpg", + "talk_title": "Cumbuca Dev: Fortalecendo o Open Source no Brasil.", + "talk_abstract": "Descubra como a Cumbuca Dev fortalece a comunidade Open Source no Brasil, promovendo inclusão, aprendizado e experiências reais para todas as pessoas interessadas em contribuir." + }, + { + "name": "Douglas Medeiros", + "bio": "Engenheiro de Software Sênior no PicPay, onde atuo como Tech Lead e PHP Skill Lead, com foco em alta performance, escalabilidade e sistemas que lidam com bilhões de registros. Criador de conteúdo tech, ativo na comunidade, palestrante e consultor técnico para times que buscam mais eficiência e qualidade nas entregas.", + "photo": "images/speakers/tba.jpg", + "talk_title": "Nem Só de Código Vive o Dev", + "talk_abstract": "O que realmente faz um dev crescer na carreira? Não, não é só saber codar bem. Nesta talk, conto como levei um choque de realidade ao descobrir que comunicação é tão essencial quanto técnica. Se você acha que \"o código fala por si\", talvez esteja perdendo a parte mais importante do jogo." + }, + { + "name": "Vilson Blanco Dauinheimer (Bwolf)", + "bio": "Vilson Blanco Dauinheimer(Bwolf) é desenvolvedor Flutter, organizador do GDG Caxias do Sul e da Flutter Meetup Network, além de mentor no Google for Startups. Atua em projetos internacionais e comunidades de tecnologia, compartilhando aprendizados sobre carreira e desenvolvimento.", + "photo": "images/speakers/tba.jpg", + "talk_title": "Abrindo Porteiras", + "talk_abstract": "Abrir porteiras é enfrentar medos e atravessar fronteiras. Nesta palestra compartilho como enfrentei o medo de trabalhar fora do país, superei barreiras de idioma e cultura e transformei a experiência internacional em evolução profissional." + }, + { + "name": "Rodrigo Bastos Vieira", + "bio": "Desenvolvendo web desde 2001, e programando em Python e Django desde 2022. Atualmente é desenvolvedor sênior e Tech Lead na Vinta Software, de Recife.", + "photo": "images/speakers/tba.jpg", + "talk_title": "Otimize suas consultas: Evitando armadilhas comuns em ORMs Python", + "talk_abstract": "Nesta palestra, vamos mostrar como identificar e corrigir um dos problemas de performance mais comuns e escondidos em ORMs Python: o famoso N+1 queries. A partir de exemplos práticos, você vai entender por que ele ocorre, como detectá‑lo e, principalmente, como evitá‑los." + } + ] +} diff --git a/content/images/speakers/belisa-arnhold.jpg b/content/images/speakers/belisa-arnhold.jpg new file mode 100644 index 0000000..51a8887 Binary files /dev/null and b/content/images/speakers/belisa-arnhold.jpg differ diff --git a/content/images/speakers/bernardo-de-castro.jpg b/content/images/speakers/bernardo-de-castro.jpg new file mode 100644 index 0000000..045fc52 Binary files /dev/null and b/content/images/speakers/bernardo-de-castro.jpg differ diff --git a/content/images/speakers/bwolf.jpg b/content/images/speakers/bwolf.jpg new file mode 100644 index 0000000..93815da Binary files /dev/null and b/content/images/speakers/bwolf.jpg differ diff --git a/content/images/speakers/cristiano-larrea.jpg b/content/images/speakers/cristiano-larrea.jpg new file mode 100644 index 0000000..2dbdec9 Binary files /dev/null and b/content/images/speakers/cristiano-larrea.jpg differ diff --git a/content/images/speakers/douglas-medeiros.jpg b/content/images/speakers/douglas-medeiros.jpg new file mode 100644 index 0000000..a0dec89 Binary files /dev/null and b/content/images/speakers/douglas-medeiros.jpg differ diff --git a/content/images/speakers/eri-bastos.jpg b/content/images/speakers/eri-bastos.jpg new file mode 100644 index 0000000..25a7dbf Binary files /dev/null and b/content/images/speakers/eri-bastos.jpg differ diff --git a/content/images/speakers/felipe-de-morais.jpg b/content/images/speakers/felipe-de-morais.jpg new file mode 100644 index 0000000..d50ebf0 Binary files /dev/null and b/content/images/speakers/felipe-de-morais.jpg differ diff --git a/content/images/speakers/gabriel-menezes.jpg b/content/images/speakers/gabriel-menezes.jpg new file mode 100644 index 0000000..3e49ea2 Binary files /dev/null and b/content/images/speakers/gabriel-menezes.jpg differ diff --git a/content/images/speakers/gian-carlo.jpg b/content/images/speakers/gian-carlo.jpg new file mode 100644 index 0000000..586f194 Binary files /dev/null and b/content/images/speakers/gian-carlo.jpg differ diff --git a/content/images/speakers/gloria-barboza.jpg b/content/images/speakers/gloria-barboza.jpg new file mode 100644 index 0000000..3f2347e Binary files /dev/null and b/content/images/speakers/gloria-barboza.jpg differ diff --git a/content/images/speakers/guilherme-garcia.jpg b/content/images/speakers/guilherme-garcia.jpg new file mode 100644 index 0000000..5cf1ba0 Binary files /dev/null and b/content/images/speakers/guilherme-garcia.jpg differ diff --git a/content/images/speakers/joao-paulo-carvalho.jpg b/content/images/speakers/joao-paulo-carvalho.jpg new file mode 100644 index 0000000..4e4d4ae Binary files /dev/null and b/content/images/speakers/joao-paulo-carvalho.jpg differ diff --git a/content/images/speakers/maria-antonia-maia.jpg b/content/images/speakers/maria-antonia-maia.jpg new file mode 100644 index 0000000..91532a1 Binary files /dev/null and b/content/images/speakers/maria-antonia-maia.jpg differ diff --git a/content/images/speakers/nilton-pimentel.jpg b/content/images/speakers/nilton-pimentel.jpg new file mode 100644 index 0000000..20564e5 Binary files /dev/null and b/content/images/speakers/nilton-pimentel.jpg differ diff --git a/content/images/speakers/perceu.jpg b/content/images/speakers/perceu.jpg new file mode 100644 index 0000000..02e870f Binary files /dev/null and b/content/images/speakers/perceu.jpg differ diff --git a/content/images/speakers/rodrigo-bastos-vieira.jpg b/content/images/speakers/rodrigo-bastos-vieira.jpg new file mode 100644 index 0000000..377c629 Binary files /dev/null and b/content/images/speakers/rodrigo-bastos-vieira.jpg differ diff --git a/src/assets/js/core/schedule.js b/src/assets/js/core/schedule.js new file mode 100644 index 0000000..a97456c --- /dev/null +++ b/src/assets/js/core/schedule.js @@ -0,0 +1,120 @@ +const SCHEDULE_SECTION_SELECTOR = '#schedule'; +const SCHEDULE_TAB_BUTTON_SELECTOR = '.schedule-tab-button'; +const SCHEDULE_TAB_CONTENT_SELECTOR = '.schedule-tab-content'; +const ACTIVE_CLASS = 'active'; +const ARIA_EXPANDED_ATTRIBUTE = 'aria-expanded'; +const MOBILE_TABLET_MEDIA_QUERY = '(max-width: 1024px)'; + +/** + * Manages the schedule tabs so that, on mobile and tablet viewports, + * only the selected day's sessions are visible. On desktop widths, + * all sessions remain visible while retaining the active state metadata. + */ +function initializeScheduleTabs() { + const scheduleSection = document.querySelector(SCHEDULE_SECTION_SELECTOR); + if (!scheduleSection) { + return; + } + + const tabButtons = Array.from(scheduleSection.querySelectorAll(SCHEDULE_TAB_BUTTON_SELECTOR)); + const tabPanels = Array.from(scheduleSection.querySelectorAll(SCHEDULE_TAB_CONTENT_SELECTOR)); + + if (!tabButtons.length || !tabPanels.length) { + return; + } + + const mediaQuery = window.matchMedia(MOBILE_TABLET_MEDIA_QUERY); + + tabButtons.forEach(button => { + button.setAttribute('type', 'button'); + }); + + const getButtonTarget = button => button.getAttribute('data-schedule-tab-target'); + const getPanelTarget = panel => panel.getAttribute('data-schedule-tab-content'); + + const showPanel = (panel, shouldShow) => { + if (mediaQuery.matches) { + panel.toggleAttribute('hidden', !shouldShow); + panel.style.display = shouldShow ? '' : 'none'; + } else { + panel.removeAttribute('hidden'); + panel.style.display = ''; + } + panel.classList.toggle(ACTIVE_CLASS, shouldShow); + }; + + const activateTab = target => { + if (!target) { + return; + } + + let matched = false; + + tabPanels.forEach(panel => { + const panelTarget = getPanelTarget(panel); + const isMatch = panelTarget === target; + if (isMatch) { + matched = true; + } + showPanel(panel, isMatch); + }); + + tabButtons.forEach(button => { + const isMatch = getButtonTarget(button) === target; + button.classList.toggle(ACTIVE_CLASS, isMatch); + button.setAttribute(ARIA_EXPANDED_ATTRIBUTE, isMatch ? 'true' : 'false'); + }); + + if (!matched && tabPanels.length) { + const fallbackTarget = getPanelTarget(tabPanels[0]); + if (fallbackTarget && fallbackTarget !== target) { + activateTab(fallbackTarget); + } + } + }; + + const syncWithViewport = () => { + if (mediaQuery.matches) { + const activePanel = + tabPanels.find(panel => panel.classList.contains(ACTIVE_CLASS)) || tabPanels[0]; + + if (activePanel) { + activateTab(getPanelTarget(activePanel)); + } + } else { + tabPanels.forEach(panel => { + panel.removeAttribute('hidden'); + panel.style.display = ''; + }); + tabButtons.forEach(button => { + button.setAttribute(ARIA_EXPANDED_ATTRIBUTE, 'true'); + }); + } + }; + + tabButtons.forEach(button => { + button.addEventListener('click', event => { + if (!mediaQuery.matches) { + return; + } + + const target = getButtonTarget(button); + if (!target) { + return; + } + + event.preventDefault(); + activateTab(target); + }); + }); + + syncWithViewport(); + + if (typeof mediaQuery.addEventListener === 'function') { + mediaQuery.addEventListener('change', syncWithViewport); + } else if (typeof mediaQuery.addListener === 'function') { + mediaQuery.addListener(syncWithViewport); + } +} + +document.addEventListener('DOMContentLoaded', initializeScheduleTabs); diff --git a/src/assets/js/main.js b/src/assets/js/main.js index dea7d38..8f90a02 100644 --- a/src/assets/js/main.js +++ b/src/assets/js/main.js @@ -11,4 +11,5 @@ import './core/countdown'; import './core/mobile-menu'; import './core/collapse'; import './core/multi-language-helper'; -import './core/smooth-scroll'; \ No newline at end of file +import './core/smooth-scroll'; +import './core/schedule'; diff --git a/src/assets/scss/main.scss b/src/assets/scss/main.scss index eb6da10..e27a71b 100644 --- a/src/assets/scss/main.scss +++ b/src/assets/scss/main.scss @@ -28,6 +28,7 @@ @import "./sections/subscribe"; // Newsletter subscribe section @import "./sections/buy-ticket"; // buy-ticket/tickets section @import "./sections/keynotes"; // Keynote speakers section +@import "./sections/schedule"; // Schedule section @import "./pages/single-post"; // Single blog post layout @import "./pages/content-list"; // Content list page layout diff --git a/src/assets/scss/sections/_criative-bg.scss b/src/assets/scss/sections/_criative-bg.scss new file mode 100644 index 0000000..80ee55a --- /dev/null +++ b/src/assets/scss/sections/_criative-bg.scss @@ -0,0 +1,13 @@ +.criative-bg { + position: relative; + overflow: hidden; + + &::after { + content: ""; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 304 304' width='304' height='304'%3E%3Cpath fill='%239C92AC' fill-opacity='0.4' d='M44.1 224a5 5 0 1 1 0 2H0v-2h44.1zm160 48a5 5 0 1 1 0 2H82v-2h122.1zm57.8-46a5 5 0 1 1 0-2H304v2h-42.1zm0 16a5 5 0 1 1 0-2H304v2h-42.1zm6.2-114a5 5 0 1 1 0 2h-86.2a5 5 0 1 1 0-2h86.2zm-256-48a5 5 0 1 1 0 2H0v-2h12.1zm185.8 34a5 5 0 1 1 0-2h86.2a5 5 0 1 1 0 2h-86.2zM258 12.1a5 5 0 1 1-2 0V0h2v12.1zm-64 208a5 5 0 1 1-2 0v-54.2a5 5 0 1 1 2 0v54.2zm48-198.2V80h62v2h-64V21.9a5 5 0 1 1 2 0zm16 16V64h46v2h-48V37.9a5 5 0 1 1 2 0zm-128 96V208h16v12.1a5 5 0 1 1-2 0V210h-16v-76.1a5 5 0 1 1 2 0zm-5.9-21.9a5 5 0 1 1 0 2H114v48H85.9a5 5 0 1 1 0-2H112v-48h12.1zm-6.2 130a5 5 0 1 1 0-2H176v-74.1a5 5 0 1 1 2 0V242h-60.1zm-16-64a5 5 0 1 1 0-2H114v48h10.1a5 5 0 1 1 0 2H112v-48h-10.1zM66 284.1a5 5 0 1 1-2 0V274H50v30h-2v-32h18v12.1zM236.1 176a5 5 0 1 1 0 2H226v94h48v32h-2v-30h-48v-98h12.1zm25.8-30a5 5 0 1 1 0-2H274v44.1a5 5 0 1 1-2 0V146h-10.1zm-64 96a5 5 0 1 1 0-2H208v-80h16v-14h-42.1a5 5 0 1 1 0-2H226v18h-16v80h-12.1zm86.2-210a5 5 0 1 1 0 2H272V0h2v32h10.1zM98 101.9V146H53.9a5 5 0 1 1 0-2H96v-42.1a5 5 0 1 1 2 0zM53.9 34a5 5 0 1 1 0-2H80V0h2v34H53.9zm60.1 3.9V66H82v64H69.9a5 5 0 1 1 0-2H80V64h32V37.9a5 5 0 1 1 2 0zM101.9 82a5 5 0 1 1 0-2H128V37.9a5 5 0 1 1 2 0V82h-28.1zm16-64a5 5 0 1 1 0-2H146v44.1a5 5 0 1 1-2 0V18h-26.1zm102.2 270a5 5 0 1 1 0 2H98v14h-2v-16h124.1zM242 149.9V160h16v34h-16v62h48v48h-2v-46h-48v-66h16v-30h-16v-12.1a5 5 0 1 1 2 0zM53.9 18a5 5 0 1 1 0-2H64V2H48V0h18v18H53.9zm112 32a5 5 0 1 1 0-2H192V0h50v2h-48v48h-28.1zm-48-48a5 5 0 0 1-9.8-2h2.07a3 3 0 1 0 5.66 0H178v34h-18V21.9a5 5 0 1 1 2 0V32h14V2h-58.1zm0 96a5 5 0 1 1 0-2H137l32-32h39V21.9a5 5 0 1 1 2 0V66h-40.17l-32 32H117.9zm28.1 90.1a5 5 0 1 1-2 0v-76.51L175.59 80H224V21.9a5 5 0 1 1 2 0V82h-49.59L146 112.41v75.69zm16 32a5 5 0 1 1-2 0v-99.51L184.59 96H300.1a5 5 0 0 1 3.9-3.9v2.07a3 3 0 0 0 0 5.66v2.07a5 5 0 0 1-3.9-3.9H185.41L162 121.41v98.69zm-144-64a5 5 0 1 1-2 0v-3.51l48-48V48h32V0h2v50H66v55.41l-48 48v2.69zM50 53.9v43.51l-48 48V208h26.1a5 5 0 1 1 0 2H0v-65.41l48-48V53.9a5 5 0 1 1 2 0zm-16 16V89.41l-34 34v-2.82l32-32V69.9a5 5 0 1 1 2 0zM12.1 32a5 5 0 1 1 0 2H9.41L0 43.41V40.6L8.59 32h3.51zm265.8 18a5 5 0 1 1 0-2h18.69l7.41-7.41v2.82L297.41 50H277.9zm-16 160a5 5 0 1 1 0-2H288v-71.41l16-16v2.82l-14 14V210h-28.1zm-208 32a5 5 0 1 1 0-2H64v-22.59L40.59 194H21.9a5 5 0 1 1 0-2H41.41L66 216.59V242H53.9zm150.2 14a5 5 0 1 1 0 2H96v-56.6L56.6 162H37.9a5 5 0 1 1 0-2h19.5L98 200.6V256h106.1zm-150.2 2a5 5 0 1 1 0-2H80v-46.59L48.59 178H21.9a5 5 0 1 1 0-2H49.41L82 208.59V258H53.9zM34 39.8v1.61L9.41 66H0v-2h8.59L32 40.59V0h2v39.8zM2 300.1a5 5 0 0 1 3.9 3.9H3.83A3 3 0 0 0 0 302.17V256h18v48h-2v-46H2v42.1zM34 241v63h-2v-62H0v-2h34v1zM17 18H0v-2h16V0h2v18h-1zm273-2h14v2h-16V0h2v16zm-32 273v15h-2v-14h-14v14h-2v-16h18v1zM0 92.1A5.02 5.02 0 0 1 6 97a5 5 0 0 1-6 4.9v-2.07a3 3 0 1 0 0-5.66V92.1zM80 272h2v32h-2v-32zm37.9 32h-2.07a3 3 0 0 0-5.66 0h-2.07a5 5 0 0 1 9.8 0zM5.9 0A5.02 5.02 0 0 1 0 5.9V3.83A3 3 0 0 0 3.83 0H5.9zm294.2 0h2.07A3 3 0 0 0 304 3.83V5.9a5 5 0 0 1-3.9-5.9zm3.9 300.1v2.07a3 3 0 0 0-1.83 1.83h-2.07a5 5 0 0 1 3.9-3.9zM97 100a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-48 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 96a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-144a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm96 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM49 36a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-32 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM33 68a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 240a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm80-176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 48a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm112 176a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm-16 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 180a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0 16a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm0-32a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16 0a3 3 0 1 0 0-6 3 3 0 0 0 0 6zM17 84a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm32 64a3 3 0 1 0 0-6 3 3 0 0 0 0 6zm16-16a3 3 0 1 0 0-6 3 3 0 0 0 0 6z'%3E%3C/path%3E%3C/svg%3E"); + position: absolute; + inset: 0; + z-index: 1; + opacity: 0.1; + } +} \ No newline at end of file diff --git a/src/assets/scss/sections/_schedule.scss b/src/assets/scss/sections/_schedule.scss index aa59ee7..f763988 100644 --- a/src/assets/scss/sections/_schedule.scss +++ b/src/assets/scss/sections/_schedule.scss @@ -1,181 +1,252 @@ -.schedule { - @extend .section; - background-color: map-get($yellow, 50); - box-shadow: $box-shadow-strong; - - &__header { - text-align: center; - margin-bottom: 4rem; - - h2 { - color: $text-dark; - margin-bottom: 0.5rem; - } +@import "./criative-bg"; - p { - color: var(--color-text); - max-width: 600px; - margin: 0 auto; - } +.category- { + &career { + --category-border-color: var(--color-category-career-border); + --category-bg-color: var(--color-category-career-bg); } - &__grid { - display: grid; - grid-template-columns: repeat(3, 1fr); - gap: 2rem; - align-items: start; + &ai { + --category-border-color: var(--color-category-ai-border); + --category-bg-color: var(--color-category-ai-bg); } -} - -.day-card { - background-color: $white; - border-radius: 8px; - overflow: hidden; - box-shadow: 0 4px 15px rgba(0, 0, 0, 0.08); - border: 1px solid var(--color-border); - - &__header { - background-color: map-get($teal, 600); - color: $white; - padding: 1.5rem; - text-align: center; - - .day-title { - font-weight: bold; - line-height: 1.2; - margin: 0; - } - .day-subtitle { - font-weight: 400; - opacity: 0.9; - margin: 0; - } + &open_source { + --category-border-color: var(--color-category-open-source-border); + --category-bg-color: var(--color-category-open-source-bg); } - &__body { - padding: 2rem 1.5rem; + &testing { + --category-border-color: var(--color-category-testing-border); + --category-bg-color: var(--color-category-testing-bg); } -} -.timeline { - list-style: none; - padding: 0; - margin: 0; - position: relative; - - &::before { - content: ''; - position: absolute; - top: 10px; - left: 28px; - bottom: 10px; - width: 2px; - background-color: map-get($slate, 500); - } - - &__item { - display: flex; - gap: 1.5rem; - position: relative; - - &:not(:last-child) { - margin-bottom: 2rem; - } + &automation { + --category-border-color: var(--color-category-automation-border); + --category-bg-color: var(--color-category-automation-bg); } - &__time { - font-weight: bold; - color: $text-dark; - flex-shrink: 0; - padding-top: 2px; - - &::before { - content: ''; - position: absolute; - left: 22px; - top: 6px; - width: 14px; - height: 14px; - border-radius: 50%; - background-color: $white; - border: 3px solid map-get($teal, 600); - } + &software_engineering { + --category-border-color: var(--color-category-software-engineering-border); + --category-bg-color: var(--color-category-software-engineering-bg); } - &__details { - h4 { - color: var(--color-text); - margin-top: 0; - margin-bottom: 0.25rem; - } - - .location { - color: map-get($slate, 600); - } + &web { + --category-border-color: var(--color-category-web-border); + --category-bg-color: var(--color-category-web-bg); } -} -.event-tag { - display: inline-block; - padding: 3px 10px; - font-weight: bold; - color: $white; - border-radius: 12px; - margin-bottom: 0.5rem; - text-transform: uppercase; - letter-spacing: 0.5px; - - &--keynote { - background-color: $tag-color-keynote; + &database { + --category-border-color: var(--color-category-database-border); + --category-bg-color: var(--color-category-database-bg); } - &--talk { - background-color: $tag-color-talk; + &data_science { + --category-border-color: var(--color-category-data-science-border); + --category-bg-color: var(--color-category-data-science-bg); } - &--interval { - background-color: $tag-color-interval; + &lightning_talks { + --category-border-color: var(--color-category-lightning_talks-border); + --category-bg-color: repeating-linear-gradient(135deg, + rgba(255, 255, 255, 0.04) 0 10px, + rgba(0, 0, 0, 0.03) 10px 20px), var(--color-category-lightning_talks-bg); } - &--workshop { - background-color: $tag-color-workshop; + &keynote { + --category-border-color: var(--color-category-keynote-border); + --category-bg-color: var(--color-category-keynote-bg); } - &--lightning { - background-color: $tag-color-lightning; + &lunch { + --category-border-color: var(--color-category-lunch-border); + --category-bg-color: repeating-linear-gradient(135deg, + rgba(255, 255, 255, 0.04) 0 10px, + rgba(0, 0, 0, 0.03) 10px 20px), var(--color-category-lunch-bg); + opacity: 0.7; } +} - &--registration { - background-color: $tag-color-registration; +.type- { + &workshop { + background: repeating-linear-gradient(40deg, + rgba(255, 255, 255, 0.02) 0 10px, + rgba(0, 0, 0, 0.02) 10px 20px), var(--category-bg-color) !important; } +} - &--end { - background-color: $tag-color-end; +.schedule { + @extend .section; + @extend .criative-bg; + @include flex-column-center; + + text-align: center; + gap: $space-8; + background-color: var(--color-schedule-bg); + + .container { + width: 100%; + max-width: var(--container-max-width); + z-index: 2; + @include responsive-container; + } + + .schedule-header { + width: 100%; + padding: $space-4; + margin-bottom: $space-6; + border-radius: $radius-6; + background-color: var(--color-schedule-bg); + box-shadow: $box-shadow-md; + + .schedule-title { + margin-bottom: $space-2; + } } } -@media (max-width: 1024px) { - .schedule-section__grid { - grid-template-columns: 1fr; - gap: 2.5rem; - } +.schedule-content { + width: 100%; } -@media (max-width: 768px) { - .schedule-section__header { - h2 {} - } +.schedule-content .header { + width: 100%; + @include flex-center; + gap: $space-3; + margin-bottom: $space-4; - .timeline__item { - gap: 1rem; + .schedule-tab-button { + width: 100%; + padding: $space-4 $space-2; + font-size: 1rem; } +} - .timeline::before { - left: 24px; +.schedule .body { + width: 100%; + display: grid; + gap: $space-4; + grid-template-columns: 1fr; + + @media (min-width: $breakpoint-lg) { + grid-template-columns: repeat(3, 1fr); } - .timeline__time::before { - left: 18px; + .schedule-tab-content { + width: 100%; + gap: $space-2; + @include flex-column-start; + display: none; + + @media (min-width: $breakpoint-md) { + display: flex; + } + + &.active { + display: flex; + } + + .schedule-event { + width: 100%; + height: 100%; + padding: $space-3; + border-radius: $radius-2; + border: 2px solid var(--color-border); + border-left: 8px solid var(--category-border-color, transparent); + background: var(--category-bg-color, var(--color-bg-secondary)); + box-shadow: $box-shadow-light; + transition: box-shadow 140ms ease, transform 140ms ease; + @include flex-column-start; + justify-content: center; + gap: $space-3; + + &:hover { + box-shadow: $box-shadow-md; + transform: translateY(-4px); + } + + .event-time { + @include flex-center; + gap: $space-2; + color: var(--color-text-secondary); + font-size: 0.9rem; + font-weight: 500; + + svg { + width: $space-4; + height: $space-4; + stroke: currentColor; + } + + .duration { + color: var(--color-text-secondary); + font-size: 0.8rem; + font-weight: 500; + } + } + + .event-category { + display: inline-block; + padding: $space-1 $space-4; + border-radius: $radius-100; + font-size: 0.75rem; + font-weight: 600; + color: $white; + text-transform: uppercase; + letter-spacing: 0.05em; + background-color: var(--category-border-color); + } + + .event-body { + width: 100%; + text-align: left; + @include flex-column-start; + + .event-title { + margin: 0 0 $space-2 0; + color: var(--color-text); + font-weight: 700; + line-height: 1.2; + overflow: hidden; + display: -webkit-box; + -webkit-line-clamp: 2; + -webkit-box-orient: vertical; + line-clamp: 2; + @include responsive-font(0.850rem, 0.905rem, 1rem); + } + + .event-speaker-container { + width: 100%; + margin-top: $space-6; + padding: $space-3 0 0 0; + border-top: 2px solid var(--color-border-subtle); + @include flex-center; + justify-content: flex-start; + gap: $space-4; + } + + .event-speaker { + @include flex-start; + gap: $space-3; + align-items: center; + + .speaker-photo { + margin: 0; + width: $space-7; + height: $space-7; + border-radius: $radius-100; + object-fit: cover; + box-shadow: $box-shadow-md; + overflow: hidden; + } + + .speaker-name { + color: var(--color-text); + font-size: 0.9rem; + font-weight: 500; + } + } + } + } } } \ No newline at end of file diff --git a/src/assets/scss/theme/colors/_dark.scss b/src/assets/scss/theme/colors/_dark.scss index 14ab6ad..3199ed6 100644 --- a/src/assets/scss/theme/colors/_dark.scss +++ b/src/assets/scss/theme/colors/_dark.scss @@ -138,6 +138,46 @@ $theme-dark: ( code-text: map-get($slate, 200), border-subtle: #3a3f44, + + // scheduling category colors (dark variants) + category-career-border: darken(map-get($green, 500), 12%), + category-career-bg: darken(map-get($green, 700), 20%), + + category-ai-border: darken(map-get($blue, 400), 12%), + category-ai-bg: darken(map-get($blue, 900), 20%), + + category-data-science-border: darken(map-get($blue, 600), 12%), + category-data-science-bg: darken(map-get($blue, 900), 30%), + + category-open-source-border: darken(map-get($purple, 500), 12%), + category-open-source-bg: darken(map-get($purple, 900), 20%), + + category-testing-border: darken(map-get($red, 500), 12%), + category-testing-bg: darken(map-get($red, 900), 20%), + + category-automation-border: darken(map-get($blue, 300), 12%), + category-automation-bg: darken(map-get($blue, 900), 20%), + + category-software-engineering-border: darken(map-get($brown, 500), 12%), + category-software-engineering-bg: darken(map-get($brown, 700), 20%), + + category-web-border: darken(map-get($py-blue, 400), 12%), + category-web-bg: darken(map-get($py-blue, 500), 20%), + + category-database-border: darken(map-get($slate, 500), 12%), + category-database-bg: darken(map-get($slate, 900), 20%), + + category-lightning_talks-border: darken(map-get($teal, 500), 12%), + category-lightning_talks-bg: darken(map-get($teal, 900), 20%), + + category-keynote-border: darken(map-get($yellow, 700), 12%), + category-keynote-bg: darken(map-get($yellow, 800), 30%), + + category-lunch-border: darken(map-get($slate, 800), 12%), + category-lunch-bg: darken(map-get($slate, 900), 20%), + + + schedule-bg: map-get($dark, 600), ); $buttons-dark: ( diff --git a/src/assets/scss/theme/colors/_light.scss b/src/assets/scss/theme/colors/_light.scss index c07386d..5087e75 100644 --- a/src/assets/scss/theme/colors/_light.scss +++ b/src/assets/scss/theme/colors/_light.scss @@ -138,6 +138,47 @@ $theme-light: ( code-text: map-get($slate, 200), border-subtle: #d3d7db, + + + // scheduling category colors + category-career-border: map-get($green, 500), + category-career-bg: map-get($green, 50), + + category-ai-border: map-get($blue, 400), + category-ai-bg: map-get($blue, 50), + + category-data-science-border: map-get($blue, 500), + category-data-science-bg: map-get($blue, 100), + + category-open-source-border: map-get($purple, 500), + category-open-source-bg: map-get($purple, 50), + + category-testing-border: map-get($red, 500), + category-testing-bg: map-get($red, 50), + + category-automation-border: map-get($blue, 300), + category-automation-bg: map-get($blue, 50), + + category-software-engineering-border: map-get($brown, 500), + category-software-engineering-bg: map-get($brown, 50), + + category-web-border: map-get($py-blue, 500), + category-web-bg: map-get($py-blue, 50), + + category-database-border: map-get($slate, 500), + category-database-bg: map-get($slate, 100), + + category-lightning_talks-border: map-get($teal, 500), + category-lightning_talks-bg: map-get($teal, 100), + + category-keynote-border: map-get($yellow, 700), + category-keynote-bg: map-get($yellow, 50), + + category-lunch-border: map-get($slate, 800), + category-lunch-bg: map-get($slate, 100), + + schedule-bg: $white, + ); $buttons-light: ( diff --git a/src/i18n/en.toml b/src/i18n/en.toml index 50b255f..1889168 100644 --- a/src/i18n/en.toml +++ b/src/i18n/en.toml @@ -98,4 +98,61 @@ other = "Register Now" [all_posts] -other = "All posts" \ No newline at end of file +other = "All posts" + +[schedule_friday_21] +other = "Friday - 21" + +[schedule_saturday_22] +other = "Saturday - 22" + +[schedule_sunday_23] +other = "Sunday - 23" + +[web] +other = "Web" + +[data_science] +other = "Data Science" + +[automation] +other = "Automation" + +[devops] +other = "DevOps" + +[lightning_talks] +other = "Lightning Talks" + +[workshop] +other = "Workshop" + +[lunch] +other = "Lunch" + +[open_source] +other = "Open Source" + +[career] +other = "Career Development" + +[database] +other = "Databases" + +[ai] +other = "AI and Machine Learning" + +[keynote] +other = "Keynote Talk" + +[software_engineering] +other = "Software Engineering" + +[testing] +other = "Testing and Quality" + +[section_schedule_title] +other = "Schedule" + +[section_schedule_description] +other = "Check out the full schedule of talks, workshops, and activities planned for the event." \ No newline at end of file diff --git a/src/i18n/es.toml b/src/i18n/es.toml index a843f04..f9d116b 100644 --- a/src/i18n/es.toml +++ b/src/i18n/es.toml @@ -97,4 +97,61 @@ other = "Más detalles aquí" other = "Regístrate ahora" [all_posts] -other = "Todas postagens" \ No newline at end of file +other = "Todas postagens" + +[schedule_friday_21] +other = "Viernes - 21" + +[schedule_saturday_22] +other = "Sábado - 22" + +[schedule_sunday_23] +other = "Domingo - 23" + +[web] +other = "Web" + +[data_science] +other = "Ciencia de Datos" + +[automation] +other = "Automatización" + +[devops] +other = "DevOps" + +[lightning_talks] +other = "Charlas Relámpago (Lightning Talks)" + +[workshop] +other = "Taller" + +[lunch] +other = "Almuerzo" + +[open_source] +other = "Código Abierto (Open Source)" + +[career] +other = "Carrera Profesional" + +[database] +other = "Bases de Datos" + +[ai] +other = "IA y Machine Learning" + +[keynote] +other = "Charla Principal" + +[software_engineering] +other = "Ingeniería de Software" + +[testing] +other = "Pruebas y Calidad" + +[section_schedule_title] +other = "Agenda" + +[section_schedule_description] +other = "Consulta la agenda completa del evento, incluyendo charlas, talleres y actividades especiales para cada día." \ No newline at end of file diff --git a/src/i18n/pt-br.toml b/src/i18n/pt-br.toml index 25b6806..0ab749f 100644 --- a/src/i18n/pt-br.toml +++ b/src/i18n/pt-br.toml @@ -98,3 +98,61 @@ other = "Inscreva-se agora" [all_posts] other = "Todas postagens" + + +[schedule_friday_21] +other = "Sexta-Feira - 21" + +[schedule_saturday_22] +other = "Sábado - 22" + +[schedule_sunday_23] +other = "Domingo - 23" + +[web] +other = "Web" + +[data_science] +other = "Ciência de Dados" + +[automation] +other = "Automação" + +[devops] +other = "DevOps" + +[lightning_talks] +other = "Palestras Relâmpago (Lightning Talks)" + +[workshop] +other = "Tutorial" + +[lunch] +other = "Almoço" + +[open_source] +other = "Open Source" + +[career] +other = "Carreira" + +[database] +other = "Banco de Dados" + +[ai] +other = "IA e Machine Learning" + +[keynote] +other = "palestra convidada" + +[software_engineering] +other = "Engenharia de Software" + +[testing] +other = "Testes e Qualidade" + +[section_schedule_title] +other = "Programação" + +[section_schedule_description] +other = "Confira a programação completa do evento, incluindo palestras, workshops e atividades especiais planejadas para cada dia." \ No newline at end of file diff --git a/src/layouts/_partials/core/image.html b/src/layouts/_partials/core/image.html index 74c78f3..f33fee8 100644 --- a/src/layouts/_partials/core/image.html +++ b/src/layouts/_partials/core/image.html @@ -7,10 +7,10 @@ {{ $image = $image | default (resources.Get "/images/placeholder.png") }} {{/* Set responsive image sizes based on avatar flag */}} -{{ $sizeSmall := cond $isAvatar "32x" "600x" }} -{{ $sizeMedium := cond $isAvatar "64x" "1000x" }} -{{ $sizeLarge := cond $isAvatar "128x" "1400x" }} -{{ $sizeFull := cond $isAvatar "128x" "1400x" }} +{{ $sizeSmall := cond $isAvatar "64x" "600x" }} +{{ $sizeMedium := cond $isAvatar "128x" "1000x" }} +{{ $sizeLarge := cond $isAvatar "256x" "1400x" }} +{{ $sizeFull := cond $isAvatar "254x" "1400x" }} {{ with $image }} {{/* Determine original image format (prefer resource MediaType, fall back to path extension) */}} @@ -19,9 +19,9 @@ {{ $isPNG := or (eq $origFormat "png") (eq $origFormat "x-png") }} {{/* Generate resized images in WebP and original/fallback formats */}} - {{ $webpSmall := .Resize (printf "%s webp q80" $sizeSmall) }} - {{ $webpMedium := .Resize (printf "%s webp q80" $sizeMedium) }} - {{ $webpLarge := .Resize (printf "%s webp q80" $sizeLarge) }} + {{ $webpSmall := .Resize (printf "%s webp q85" $sizeSmall) }} + {{ $webpMedium := .Resize (printf "%s webp q85" $sizeMedium) }} + {{ $webpLarge := .Resize (printf "%s webp q85" $sizeLarge) }} {{ $fallbackConfig := cond $isPNG (dict "format" "png" "mime" "image/png") (dict "format" "jpg q90" "mime" "image/jpeg") }} {{ $fallback := .Resize (printf "%s %s" $sizeFull (index $fallbackConfig "format")) }} diff --git a/src/layouts/_partials/sections/schedule.html b/src/layouts/_partials/sections/schedule.html index 18befdd..9ad922a 100644 --- a/src/layouts/_partials/sections/schedule.html +++ b/src/layouts/_partials/sections/schedule.html @@ -1,12 +1,91 @@ -
-
- {{/* Section title for the schedule */}} -

- Programação -

- {{/* Section description text */}} -

- description -

-
+{{ $content := .Site.Data.section.schedule }} + +
+
+
+

+ {{ T "section_schedule_title" }} +

+

+ {{ T "section_schedule_description" }} +

+ +
+
+
+ {{ range $content }} + + {{ end }} +
+
+ {{ range $content }} +
+ {{ range .sessions }} +
+
+ {{ if .category }} + + {{ T (printf .category) }} + + {{ end }} +
+
+

{{ .title }}

+ {{- $speakers := slice -}} + {{- with .speaker }} + {{- if reflect.IsSlice . }} + {{- range . }} + {{- if reflect.IsMap . }} + {{- $speakers = $speakers | append . }} + {{- else }} + {{- $speakers = $speakers | append (dict "name" .) }} + {{- end }} + {{- end }} + {{- else if reflect.IsMap . }} + {{- $speakers = $speakers | append . }} + {{- else }} + {{- $speakers = $speakers | append (dict "name" .) }} + {{- end }} + {{- end }} + +
+ {{ partial "svg/icons/clock.svg" }} + + ({{ .duration }}) +
+ + {{ if gt (len $speakers) 0 }} +
+ {{- range $index, $speaker := $speakers }} +
+ {{- with $speaker.photo }} + {{ partial "core/image.html" (dict "src" . "alt" $speaker.name "avatar" true "className" "speaker-photo") }} + {{- end }} + {{ $speaker.name }} +
+ {{- end }} +
+ {{ end }} +
+
+ {{ end }} +
+ {{ end }} +
+
+
\ No newline at end of file diff --git a/src/layouts/home.html b/src/layouts/home.html index 2b42c46..9682d33 100644 --- a/src/layouts/home.html +++ b/src/layouts/home.html @@ -5,6 +5,7 @@ {{ partial "sections/keynotes.html" . }} {{/* Keynotes section: keynote speakers */}} {{/* partial "sections/cfp.html" . /*}} {{/* Call for Papers section: submission info */}} {{ partial "sections/buy-ticket.html" . }} {{/* Buy a ticket */}} +{{ partial "sections/schedule.html" . }} {{/* Schedule section: event schedule */}} {{ partial "sections/blog.html" . }} {{/* Blog section: latest news or posts */}} {{ partial "sections/sponsors.html" . }} {{/* Sponsors section: sponsor logos/info */}} {{ partial "sections/supporters.html" . }} {{/* Supporters section: supporter logos/info */}}