Initial commit
@@ -0,0 +1,57 @@
|
||||
<?php
|
||||
/**
|
||||
* Not found template.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
get_header();
|
||||
|
||||
$gustavoo_recent_posts = get_posts(
|
||||
array(
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => 3,
|
||||
'ignore_sticky_posts' => true,
|
||||
'no_found_rows' => true,
|
||||
)
|
||||
);
|
||||
?>
|
||||
|
||||
<main id="primary" class="site-main error-404">
|
||||
<section class="page-hero page-hero--error" aria-labelledby="error-title">
|
||||
<div class="site-shell page-hero__inner">
|
||||
<p class="eyebrow">404</p>
|
||||
<h1 id="error-title" class="page-hero__title"><?php esc_html_e( 'Esta página saiu do mapa.', 'gustavoo-portfolio' ); ?></h1>
|
||||
<p class="page-hero__description"><?php esc_html_e( 'O endereço pode ter mudado ou não existir mais. Pesquise pelo conteúdo ou retorne ao início.', 'gustavoo-portfolio' ); ?></p>
|
||||
<div class="page-hero__actions">
|
||||
<a class="button button--primary" href="<?php echo esc_url( home_url( '/' ) ); ?>"><?php esc_html_e( 'Voltar ao início', 'gustavoo-portfolio' ); ?> <span aria-hidden="true">→</span></a>
|
||||
</div>
|
||||
<div class="page-hero__search"><?php get_search_form(); ?></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<?php if ( $gustavoo_recent_posts ) : ?>
|
||||
<section class="section section--error-posts" aria-labelledby="error-posts-title">
|
||||
<div class="site-shell">
|
||||
<header class="section__header">
|
||||
<p class="eyebrow"><?php esc_html_e( 'Continue explorando', 'gustavoo-portfolio' ); ?></p>
|
||||
<h2 id="error-posts-title" class="section__title"><?php esc_html_e( 'Artigos recentes', 'gustavoo-portfolio' ); ?></h2>
|
||||
</header>
|
||||
<div class="posts-grid">
|
||||
<?php
|
||||
global $post;
|
||||
foreach ( $gustavoo_recent_posts as $post ) {
|
||||
setup_postdata( $post );
|
||||
get_template_part( 'template-parts/global/post-card' );
|
||||
}
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
/**
|
||||
* Category, tag, author, and date archives.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<main id="primary" class="site-main archive-main">
|
||||
<header class="page-hero page-hero--archive">
|
||||
<div class="site-shell page-hero__inner">
|
||||
<p class="eyebrow"><?php esc_html_e( 'Arquivo', 'gustavoo-portfolio' ); ?></p>
|
||||
<h1 class="page-hero__title"><?php echo esc_html( wp_strip_all_tags( get_the_archive_title() ) ); ?></h1>
|
||||
<?php if ( get_the_archive_description() ) : ?>
|
||||
<div class="page-hero__description prose"><?php echo wp_kses_post( get_the_archive_description() ); ?></div>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="site-shell article-layout">
|
||||
<div class="article-layout__main">
|
||||
<?php if ( have_posts() ) : ?>
|
||||
<div class="posts-grid">
|
||||
<?php
|
||||
while ( have_posts() ) {
|
||||
the_post();
|
||||
get_template_part( 'template-parts/global/post-card' );
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php gustavoo_portfolio_pagination(); ?>
|
||||
<?php else : ?>
|
||||
<?php get_template_part( 'template-parts/content/content', 'none' ); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php get_sidebar(); ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,57 @@
|
||||
@font-face {
|
||||
font-family: "Inter";
|
||||
font-style: normal;
|
||||
font-weight: 100 900;
|
||||
font-display: swap;
|
||||
src: url("../fonts/inter-variable.woff2") format("woff2-variations");
|
||||
}
|
||||
|
||||
.editor-styles-wrapper {
|
||||
color: #d4dde3;
|
||||
background: #071624;
|
||||
font-family: "Inter", system-ui, sans-serif;
|
||||
font-size: 17px;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
.editor-styles-wrapper .wp-block {
|
||||
max-width: 760px;
|
||||
}
|
||||
|
||||
.editor-styles-wrapper .wp-block[data-align="wide"] {
|
||||
max-width: 1160px;
|
||||
}
|
||||
|
||||
.editor-styles-wrapper h1,
|
||||
.editor-styles-wrapper h2,
|
||||
.editor-styles-wrapper h3,
|
||||
.editor-styles-wrapper h4,
|
||||
.editor-styles-wrapper h5,
|
||||
.editor-styles-wrapper h6 {
|
||||
color: #f5f8fa;
|
||||
font-weight: 750;
|
||||
line-height: 1.1;
|
||||
letter-spacing: -0.035em;
|
||||
}
|
||||
|
||||
.editor-styles-wrapper a {
|
||||
color: #74d5c7;
|
||||
}
|
||||
|
||||
.editor-styles-wrapper blockquote {
|
||||
padding-left: 1.5rem;
|
||||
color: #b8c5ce;
|
||||
border-left: 3px solid #74d5c7;
|
||||
}
|
||||
|
||||
.editor-styles-wrapper code,
|
||||
.editor-styles-wrapper pre {
|
||||
color: #d9fdf7;
|
||||
background: #040d16;
|
||||
border-radius: 8px;
|
||||
font-family: "SFMono-Regular", Consolas, monospace;
|
||||
}
|
||||
|
||||
.editor-styles-wrapper img {
|
||||
border-radius: 10px;
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter)
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 492 KiB |
|
After Width: | Height: | Size: 67 KiB |
|
After Width: | Height: | Size: 38 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 38 KiB |
@@ -0,0 +1,273 @@
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
const ready = (callback) => {
|
||||
if (document.readyState === "loading") {
|
||||
document.addEventListener("DOMContentLoaded", callback, { once: true });
|
||||
return;
|
||||
}
|
||||
|
||||
callback();
|
||||
};
|
||||
|
||||
ready(function () {
|
||||
const header = document.querySelector(".site-header");
|
||||
const toggle = document.querySelector("[data-nav-toggle], .nav-toggle, .menu-toggle");
|
||||
const navigation = document.querySelector("[data-primary-nav], .primary-nav, .primary-navigation");
|
||||
const reduceMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
|
||||
let lastFocusedElement = null;
|
||||
|
||||
const updateHeader = () => {
|
||||
if (!header) {
|
||||
return;
|
||||
}
|
||||
|
||||
header.classList.toggle("is-scrolled", window.scrollY > 24);
|
||||
};
|
||||
|
||||
updateHeader();
|
||||
window.addEventListener("scroll", updateHeader, { passive: true });
|
||||
|
||||
if (toggle && navigation) {
|
||||
const drawerClose = navigation.querySelector("[data-nav-close]");
|
||||
const navigationParent = navigation.parentNode;
|
||||
const navigationNextSibling = navigation.nextSibling;
|
||||
let navigationIsDrawer = false;
|
||||
|
||||
const placeNavigation = (asDrawer) => {
|
||||
if (asDrawer && !navigationIsDrawer) {
|
||||
document.body.appendChild(navigation);
|
||||
navigationIsDrawer = true;
|
||||
} else if (!asDrawer && navigationIsDrawer) {
|
||||
navigationParent.insertBefore(navigation, navigationNextSibling);
|
||||
navigationIsDrawer = false;
|
||||
}
|
||||
};
|
||||
|
||||
if (!navigation.id) {
|
||||
navigation.id = "site-navigation";
|
||||
}
|
||||
|
||||
toggle.setAttribute("aria-controls", navigation.id);
|
||||
toggle.setAttribute("aria-expanded", "false");
|
||||
navigation.setAttribute("aria-hidden", "true");
|
||||
|
||||
const focusableSelector = [
|
||||
"a[href]",
|
||||
"button:not([disabled])",
|
||||
"input:not([disabled])",
|
||||
"select:not([disabled])",
|
||||
"textarea:not([disabled])",
|
||||
"[tabindex]:not([tabindex='-1'])",
|
||||
].join(",");
|
||||
|
||||
const closeMenu = (restoreFocus) => {
|
||||
toggle.setAttribute("aria-expanded", "false");
|
||||
const toggleLabel = toggle.querySelector(".menu-toggle__label");
|
||||
if (toggleLabel && window.gustavooPortfolioNavigation) {
|
||||
toggleLabel.textContent = window.gustavooPortfolioNavigation.expand;
|
||||
}
|
||||
navigation.setAttribute("aria-hidden", "true");
|
||||
navigation.classList.remove("is-open");
|
||||
navigation.classList.remove("has-more-content");
|
||||
document.body.classList.remove("nav-open");
|
||||
|
||||
if (restoreFocus && lastFocusedElement) {
|
||||
lastFocusedElement.focus();
|
||||
}
|
||||
};
|
||||
|
||||
const openMenu = () => {
|
||||
lastFocusedElement = document.activeElement;
|
||||
toggle.setAttribute("aria-expanded", "true");
|
||||
const toggleLabel = toggle.querySelector(".menu-toggle__label");
|
||||
if (toggleLabel && window.gustavooPortfolioNavigation) {
|
||||
toggleLabel.textContent = window.gustavooPortfolioNavigation.collapse;
|
||||
}
|
||||
navigation.setAttribute("aria-hidden", "false");
|
||||
navigation.classList.add("is-open");
|
||||
document.body.classList.add("nav-open");
|
||||
|
||||
window.requestAnimationFrame(function () {
|
||||
updateNavigationScrollHint();
|
||||
});
|
||||
|
||||
const firstFocusable = navigation.querySelector(focusableSelector);
|
||||
if (firstFocusable) {
|
||||
window.requestAnimationFrame(() => firstFocusable.focus());
|
||||
}
|
||||
};
|
||||
|
||||
const updateNavigationScrollHint = () => {
|
||||
const hasMoreContent = navigation.scrollHeight > navigation.clientHeight + 4
|
||||
&& navigation.scrollTop + navigation.clientHeight < navigation.scrollHeight - 4;
|
||||
navigation.classList.toggle("has-more-content", hasMoreContent);
|
||||
};
|
||||
|
||||
toggle.addEventListener("click", function () {
|
||||
if (toggle.getAttribute("aria-expanded") === "true") {
|
||||
closeMenu(false);
|
||||
} else {
|
||||
openMenu();
|
||||
}
|
||||
});
|
||||
|
||||
if (drawerClose) {
|
||||
drawerClose.addEventListener("click", function () {
|
||||
closeMenu(true);
|
||||
});
|
||||
}
|
||||
|
||||
navigation.addEventListener("click", function (event) {
|
||||
if (event.target.closest("a")) {
|
||||
closeMenu(false);
|
||||
}
|
||||
});
|
||||
|
||||
navigation.addEventListener("scroll", updateNavigationScrollHint, { passive: true });
|
||||
window.addEventListener("resize", updateNavigationScrollHint, { passive: true });
|
||||
|
||||
document.addEventListener("keydown", function (event) {
|
||||
if (toggle.getAttribute("aria-expanded") !== "true") {
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key === "Escape") {
|
||||
event.preventDefault();
|
||||
closeMenu(true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (event.key !== "Tab") {
|
||||
return;
|
||||
}
|
||||
|
||||
const focusable = Array.from(navigation.querySelectorAll(focusableSelector));
|
||||
focusable.push(toggle);
|
||||
|
||||
if (!focusable.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const first = focusable[0];
|
||||
const last = focusable[focusable.length - 1];
|
||||
|
||||
if (event.shiftKey && document.activeElement === first) {
|
||||
event.preventDefault();
|
||||
last.focus();
|
||||
} else if (!event.shiftKey && document.activeElement === last) {
|
||||
event.preventDefault();
|
||||
first.focus();
|
||||
}
|
||||
});
|
||||
|
||||
const desktopQuery = window.matchMedia("(min-width: 921px)");
|
||||
const handleDesktop = (event) => {
|
||||
placeNavigation(!event.matches);
|
||||
|
||||
if (event.matches) {
|
||||
closeMenu(false);
|
||||
navigation.removeAttribute("aria-hidden");
|
||||
} else if (toggle.getAttribute("aria-expanded") !== "true") {
|
||||
navigation.setAttribute("aria-hidden", "true");
|
||||
}
|
||||
};
|
||||
|
||||
handleDesktop(desktopQuery);
|
||||
desktopQuery.addEventListener("change", handleDesktop);
|
||||
}
|
||||
|
||||
if (window.location.hash.length > 1) {
|
||||
const hashId = decodeURIComponent(window.location.hash.slice(1));
|
||||
const hashTarget = document.getElementById(hashId);
|
||||
|
||||
if (hashTarget) {
|
||||
window.requestAnimationFrame(function () {
|
||||
window.setTimeout(function () {
|
||||
hashTarget.scrollIntoView({ behavior: "auto", block: "start" });
|
||||
}, 120);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
document.querySelectorAll('a[href^="#"]:not([href="#"])').forEach(function (link) {
|
||||
link.addEventListener("click", function (event) {
|
||||
const id = link.getAttribute("href").slice(1);
|
||||
const target = document.getElementById(id);
|
||||
|
||||
if (!target) {
|
||||
return;
|
||||
}
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
// The header becomes fixed after the page is scrolled, so
|
||||
// scrollIntoView() cannot scroll the document when targeting it.
|
||||
if (id === "masthead") {
|
||||
window.scrollTo({
|
||||
top: 0,
|
||||
behavior: reduceMotion.matches ? "auto" : "smooth",
|
||||
});
|
||||
} else {
|
||||
target.scrollIntoView({
|
||||
behavior: reduceMotion.matches ? "auto" : "smooth",
|
||||
block: "start",
|
||||
});
|
||||
}
|
||||
|
||||
if (window.history && window.history.replaceState) {
|
||||
window.history.replaceState(null, "", `#${id}`);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
const revealItems = Array.from(document.querySelectorAll("[data-reveal]"));
|
||||
|
||||
if (revealItems.length && "IntersectionObserver" in window && !reduceMotion.matches) {
|
||||
document.documentElement.classList.add("has-reveal");
|
||||
|
||||
const revealObserver = new IntersectionObserver(
|
||||
function (entries, observer) {
|
||||
entries.forEach(function (entry) {
|
||||
if (!entry.isIntersecting) {
|
||||
return;
|
||||
}
|
||||
|
||||
const delay = Number.parseInt(entry.target.dataset.revealDelay || "0", 10);
|
||||
if (delay > 0) {
|
||||
entry.target.style.transitionDelay = `${Math.min(delay, 500)}ms`;
|
||||
}
|
||||
|
||||
entry.target.classList.add("is-visible");
|
||||
observer.unobserve(entry.target);
|
||||
});
|
||||
},
|
||||
{ rootMargin: "0px 0px -8%", threshold: 0.12 }
|
||||
);
|
||||
|
||||
revealItems.forEach((item) => revealObserver.observe(item));
|
||||
} else {
|
||||
revealItems.forEach((item) => item.classList.add("is-visible"));
|
||||
}
|
||||
|
||||
const progress = document.querySelector("[data-reading-progress]");
|
||||
const article = document.querySelector(".entry-content");
|
||||
|
||||
if (progress && article) {
|
||||
const updateProgress = () => {
|
||||
const articleTop = article.getBoundingClientRect().top + window.scrollY;
|
||||
const articleHeight = article.offsetHeight;
|
||||
const viewportHeight = window.innerHeight;
|
||||
const distance = articleHeight - viewportHeight;
|
||||
const current = window.scrollY - articleTop;
|
||||
const percentage = distance > 0 ? Math.min(100, Math.max(0, (current / distance) * 100)) : 100;
|
||||
progress.style.setProperty("--reading-progress", `${percentage}%`);
|
||||
progress.setAttribute("aria-valuenow", String(Math.round(percentage)));
|
||||
};
|
||||
|
||||
updateProgress();
|
||||
window.addEventListener("scroll", updateProgress, { passive: true });
|
||||
window.addEventListener("resize", updateProgress, { passive: true });
|
||||
}
|
||||
});
|
||||
})();
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
/** Category news archive. @package Gustavo_Portfolio */
|
||||
|
||||
get_header();
|
||||
?>
|
||||
<main id="primary" class="site-main news-index news-index--category">
|
||||
<header class="news-page-heading">
|
||||
<div class="site-shell">
|
||||
<h1><?php single_cat_title(); ?></h1>
|
||||
<?php if ( category_description() ) : ?><div class="news-page-heading__description"><?php echo wp_kses_post( category_description() ); ?></div><?php endif; ?>
|
||||
</div>
|
||||
</header>
|
||||
<div class="site-shell news-index__content">
|
||||
<?php if ( have_posts() ) : ?>
|
||||
<div class="latest-news-grid">
|
||||
<?php
|
||||
$gustavoo_news_index = 0;
|
||||
$gustavoo_displayed_post_ids = array();
|
||||
while ( have_posts() ) {
|
||||
the_post();
|
||||
$gustavoo_displayed_post_ids[] = get_the_ID();
|
||||
get_template_part( 'template-parts/global/latest-news-card', null, array( 'featured' => 0 === $gustavoo_news_index ) );
|
||||
$gustavoo_news_index++;
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php get_template_part( 'template-parts/global/latest-news-list', null, array( 'exclude' => $gustavoo_displayed_post_ids, 'category_id' => get_queried_object_id() ) ); ?>
|
||||
<?php gustavoo_portfolio_pagination(); ?>
|
||||
<?php else : ?>
|
||||
<?php get_template_part( 'template-parts/content/content', 'none' ); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
<?php get_footer(); ?>
|
||||
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
/**
|
||||
* Comments template.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( post_password_required() ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
|
||||
<section id="comments" class="comments-area">
|
||||
<?php if ( have_comments() ) : ?>
|
||||
<h2 class="comments-title">
|
||||
<?php
|
||||
$gustavoo_comment_count = get_comments_number();
|
||||
printf(
|
||||
/* translators: 1: comment count, 2: post title. */
|
||||
esc_html( _n( '%1$s comentário em “%2$s”', '%1$s comentários em “%2$s”', $gustavoo_comment_count, 'gustavoo-portfolio' ) ),
|
||||
esc_html( number_format_i18n( $gustavoo_comment_count ) ),
|
||||
esc_html( get_the_title() )
|
||||
);
|
||||
?>
|
||||
</h2>
|
||||
|
||||
<ol class="comment-list">
|
||||
<?php
|
||||
wp_list_comments(
|
||||
array(
|
||||
'avatar_size' => 64,
|
||||
'short_ping' => true,
|
||||
'style' => 'ol',
|
||||
)
|
||||
);
|
||||
?>
|
||||
</ol>
|
||||
|
||||
<?php
|
||||
the_comments_navigation(
|
||||
array(
|
||||
'prev_text' => sprintf( '<span aria-hidden="true">←</span> %s', esc_html__( 'Comentários anteriores', 'gustavoo-portfolio' ) ),
|
||||
'next_text' => sprintf( '%s <span aria-hidden="true">→</span>', esc_html__( 'Próximos comentários', 'gustavoo-portfolio' ) ),
|
||||
)
|
||||
);
|
||||
?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( ! comments_open() && get_comments_number() ) : ?>
|
||||
<p class="no-comments"><?php esc_html_e( 'Os comentários estão encerrados.', 'gustavoo-portfolio' ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php
|
||||
comment_form(
|
||||
array(
|
||||
'class_submit' => 'submit button button--primary',
|
||||
'label_submit' => __( 'Publicar comentário', 'gustavoo-portfolio' ),
|
||||
'title_reply' => __( 'Deixe um comentário', 'gustavoo-portfolio' ),
|
||||
'title_reply_before' => '<h2 id="reply-title" class="comment-reply-title">',
|
||||
'title_reply_after' => '</h2>',
|
||||
'comment_notes_before' => '<p class="comment-notes">' . esc_html__( 'Seu endereço de e-mail não será publicado. Campos obrigatórios são indicados.', 'gustavoo-portfolio' ) . '</p>',
|
||||
)
|
||||
);
|
||||
?>
|
||||
</section>
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/**
|
||||
* Site footer and the global newsletter CTA.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
get_template_part( 'template-parts/global/newsletter-cta' );
|
||||
?>
|
||||
|
||||
<footer id="colophon" class="site-footer">
|
||||
<div class="site-shell site-footer__main">
|
||||
<div class="site-footer__brand">
|
||||
<div class="site-footer__brand-row">
|
||||
<?php gustavoo_portfolio_the_brand(); ?>
|
||||
<p class="site-footer__name"><?php echo esc_html( get_bloginfo( 'name' ) ); ?></p>
|
||||
</div>
|
||||
<p><?php echo esc_html( gustavoo_portfolio_get_setting( 'hero_description' ) ); ?></p>
|
||||
<?php gustavoo_portfolio_social_links( 'social-links social-links--footer' ); ?>
|
||||
</div>
|
||||
|
||||
<?php if ( has_nav_menu( 'footer' ) ) : ?>
|
||||
<nav class="footer-navigation" aria-label="<?php esc_attr_e( 'Navegação do rodapé', 'gustavoo-portfolio' ); ?>">
|
||||
<?php
|
||||
wp_nav_menu(
|
||||
array(
|
||||
'theme_location' => 'footer',
|
||||
'menu_class' => 'footer-menu',
|
||||
'container' => false,
|
||||
'depth' => 1,
|
||||
'fallback_cb' => false,
|
||||
)
|
||||
);
|
||||
?>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<div class="site-shell site-footer__bottom">
|
||||
<p>
|
||||
<?php
|
||||
printf(
|
||||
/* translators: 1: current year, 2: site name. */
|
||||
esc_html__( '© %1$s %2$s. Todos os direitos reservados.', 'gustavoo-portfolio' ),
|
||||
esc_html( wp_date( 'Y' ) ),
|
||||
esc_html( get_bloginfo( 'name' ) )
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<a href="#masthead" class="back-to-top"><?php esc_html_e( 'Voltar ao topo', 'gustavoo-portfolio' ); ?> <span aria-hidden="true">↑</span></a>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<?php
|
||||
if ( is_front_page() ) {
|
||||
gustavoo_portfolio_the_whatsapp_float();
|
||||
}
|
||||
?>
|
||||
|
||||
<?php wp_footer(); ?>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Portfolio landing page.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<main id="primary" class="site-main front-page">
|
||||
<?php get_template_part( 'template-parts/front/hero' ); ?>
|
||||
<?php get_template_part( 'template-parts/front/about' ); ?>
|
||||
<?php get_template_part( 'template-parts/front/services' ); ?>
|
||||
<?php get_template_part( 'template-parts/front/projects' ); ?>
|
||||
|
||||
<?php if ( is_page() && have_posts() ) : ?>
|
||||
<?php
|
||||
while ( have_posts() ) {
|
||||
the_post();
|
||||
$gustavoo_front_content = trim( (string) get_the_content() );
|
||||
|
||||
if ( $gustavoo_front_content ) {
|
||||
?>
|
||||
<div class="section section--custom-content">
|
||||
<div class="site-shell entry-content">
|
||||
<?php the_content(); ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php get_template_part( 'template-parts/front/contact' ); ?>
|
||||
<?php get_template_part( 'template-parts/front/posts' ); ?>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
/**
|
||||
* Gustavo Portfolio theme bootstrap.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$gustavoo_portfolio_includes = array(
|
||||
'/inc/defaults.php',
|
||||
'/inc/setup.php',
|
||||
'/inc/enqueue.php',
|
||||
'/inc/template-tags.php',
|
||||
'/inc/customizer.php',
|
||||
'/inc/forms.php',
|
||||
'/inc/widgets.php',
|
||||
);
|
||||
|
||||
foreach ( $gustavoo_portfolio_includes as $gustavoo_portfolio_file ) {
|
||||
$gustavoo_portfolio_path = get_theme_file_path( $gustavoo_portfolio_file );
|
||||
|
||||
if ( file_exists( $gustavoo_portfolio_path ) ) {
|
||||
require_once $gustavoo_portfolio_path;
|
||||
}
|
||||
}
|
||||
|
||||
unset( $gustavoo_portfolio_file, $gustavoo_portfolio_includes, $gustavoo_portfolio_path );
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
/**
|
||||
* Site header.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?><!doctype html>
|
||||
<html <?php language_attributes(); ?>>
|
||||
<head>
|
||||
<meta charset="<?php bloginfo( 'charset' ); ?>">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<?php wp_head(); ?>
|
||||
</head>
|
||||
<body <?php body_class(); ?>>
|
||||
<?php wp_body_open(); ?>
|
||||
<a class="skip-link screen-reader-text" href="#primary"><?php esc_html_e( 'Pular para o conteúdo', 'gustavoo-portfolio' ); ?></a>
|
||||
|
||||
<?php
|
||||
$gustavoo_is_editorial_page = is_home() || is_category() || is_singular( 'post' );
|
||||
$gustavoo_primary_shortcut_attr = is_customize_preview() ? ' data-customize-partial-id="gustavoo_portfolio_menu_shortcut_primary"' : '';
|
||||
?>
|
||||
<header id="masthead" class="site-header<?php echo is_front_page() ? ' site-header--overlay' : ''; ?><?php echo $gustavoo_is_editorial_page ? ' site-header--editorial' : ''; ?>">
|
||||
<div class="site-shell site-header__inner">
|
||||
<div class="site-branding">
|
||||
<?php gustavoo_portfolio_the_brand(); ?>
|
||||
<a class="site-branding__text" href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home">
|
||||
<span class="site-branding__name"><?php echo esc_html( get_bloginfo( 'name' ) ); ?></span>
|
||||
<span class="site-branding__tagline site-branding__tagline--full"><?php esc_html_e( 'Desenvolvedor Full Stack | Web, Mobile, Infraestrutura & Automação', 'gustavoo-portfolio' ); ?></span>
|
||||
<span class="site-branding__tagline site-branding__tagline--short"><?php esc_html_e( 'Desenvolvedor Full Stack | Web, Mobile, Infraestrutura & Automação', 'gustavoo-portfolio' ); ?></span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<button class="menu-toggle" type="button" aria-expanded="false" aria-controls="primary-menu">
|
||||
<span class="menu-toggle__label"><?php esc_html_e( 'Abrir menu', 'gustavoo-portfolio' ); ?></span>
|
||||
<span class="menu-toggle__icon" aria-hidden="true"><span></span><span></span><span></span></span>
|
||||
</button>
|
||||
|
||||
<nav id="site-navigation" class="primary-navigation" aria-label="<?php esc_attr_e( 'Navegação principal', 'gustavoo-portfolio' ); ?>"<?php echo $gustavoo_primary_shortcut_attr; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Static attribute. ?>>
|
||||
<button class="menu-drawer-close" type="button" data-nav-close aria-label="<?php esc_attr_e( 'Fechar menu', 'gustavoo-portfolio' ); ?>">
|
||||
<span aria-hidden="true"></span>
|
||||
<span aria-hidden="true"></span>
|
||||
</button>
|
||||
<?php
|
||||
wp_nav_menu(
|
||||
array(
|
||||
'theme_location' => 'primary',
|
||||
'menu_id' => 'primary-menu',
|
||||
'menu_class' => 'primary-menu',
|
||||
'container' => false,
|
||||
'fallback_cb' => 'gustavoo_portfolio_primary_menu_fallback',
|
||||
'depth' => 2,
|
||||
)
|
||||
);
|
||||
?>
|
||||
<?php if ( $gustavoo_is_editorial_page ) : ?>
|
||||
<?php gustavoo_portfolio_mobile_news_category_menu(); ?>
|
||||
<?php endif; ?>
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<?php
|
||||
if ( $gustavoo_is_editorial_page ) {
|
||||
gustavoo_portfolio_news_category_menu();
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/**
|
||||
* Posts page.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
get_header();
|
||||
|
||||
?>
|
||||
|
||||
<main id="primary" class="site-main news-index">
|
||||
<header class="news-page-heading"><div class="site-shell"><h1><?php esc_html_e( 'Últimas notícias', 'gustavoo-portfolio' ); ?></h1></div></header>
|
||||
|
||||
<div class="site-shell news-index__content">
|
||||
<?php if ( have_posts() ) : ?>
|
||||
<div class="latest-news-grid">
|
||||
<?php
|
||||
$gustavoo_news_index = 0;
|
||||
$gustavoo_displayed_post_ids = array();
|
||||
while ( have_posts() ) {
|
||||
the_post();
|
||||
$gustavoo_displayed_post_ids[] = get_the_ID();
|
||||
get_template_part( 'template-parts/global/latest-news-card', null, array( 'featured' => 0 === $gustavoo_news_index ) );
|
||||
$gustavoo_news_index++;
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php get_template_part( 'template-parts/global/latest-news-list', null, array( 'exclude' => $gustavoo_displayed_post_ids ) ); ?>
|
||||
<?php gustavoo_portfolio_pagination(); ?>
|
||||
<?php else : ?>
|
||||
<?php get_template_part( 'template-parts/content/content', 'none' ); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,212 @@
|
||||
<?php
|
||||
/**
|
||||
* Native WordPress Customizer integration and selective-refresh shortcuts.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/** Sanitize a URL or an in-page anchor used by theme calls to action. */
|
||||
function gustavoo_portfolio_customize_link( $value ) {
|
||||
$value = trim( sanitize_text_field( (string) $value ) );
|
||||
|
||||
if ( preg_match( '/^#[A-Za-z][A-Za-z0-9_:.-]*$/', $value ) ) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return esc_url_raw( $value, array( 'http', 'https', 'mailto', 'tel' ) );
|
||||
}
|
||||
|
||||
/** Render a template part for a selective-refresh partial. */
|
||||
function gustavoo_portfolio_customize_render_part( $slug ) {
|
||||
ob_start();
|
||||
get_template_part( $slug );
|
||||
return (string) ob_get_clean();
|
||||
}
|
||||
|
||||
/** Register the portfolio content controls in Appearance > Customize. */
|
||||
function gustavoo_portfolio_customize_register( $wp_customize ) {
|
||||
$wp_customize->add_panel(
|
||||
'gustavoo_portfolio_content',
|
||||
array(
|
||||
'title' => __( 'Conteúdo do tema', 'gustavoo-portfolio' ),
|
||||
'description' => __( 'Edite os conteúdos exibidos no site e use os lápis na prévia para ir direto à seção desejada.', 'gustavoo-portfolio' ),
|
||||
'priority' => 30,
|
||||
)
|
||||
);
|
||||
|
||||
$sections = array(
|
||||
'hero' => __( 'Hero', 'gustavoo-portfolio' ),
|
||||
'about' => __( 'Sobre', 'gustavoo-portfolio' ),
|
||||
'services' => __( 'Serviços', 'gustavoo-portfolio' ),
|
||||
'projects' => __( 'Projetos', 'gustavoo-portfolio' ),
|
||||
'blog' => __( 'Blog', 'gustavoo-portfolio' ),
|
||||
'contact' => __( 'Contato', 'gustavoo-portfolio' ),
|
||||
'newsletter' => __( 'Newsletter', 'gustavoo-portfolio' ),
|
||||
'social' => __( 'Redes sociais', 'gustavoo-portfolio' ),
|
||||
);
|
||||
|
||||
foreach ( $sections as $id => $title ) {
|
||||
$wp_customize->add_section(
|
||||
'gustavoo_portfolio_' . $id,
|
||||
array(
|
||||
'title' => $title,
|
||||
'panel' => 'gustavoo_portfolio_content',
|
||||
'priority' => 10,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$fields = array(
|
||||
'hero_eyebrow' => array( 'hero', __( 'Sobretítulo', 'gustavoo-portfolio' ), 'text' ),
|
||||
'hero_title' => array( 'hero', __( 'Título', 'gustavoo-portfolio' ), 'text' ),
|
||||
'hero_description' => array( 'hero', __( 'Descrição', 'gustavoo-portfolio' ), 'textarea' ),
|
||||
'hero_primary_label' => array( 'hero', __( 'Botão principal — texto', 'gustavoo-portfolio' ), 'text' ),
|
||||
'hero_primary_url' => array( 'hero', __( 'Botão principal — link', 'gustavoo-portfolio' ), 'link' ),
|
||||
'hero_secondary_label' => array( 'hero', __( 'Botão secundário — texto', 'gustavoo-portfolio' ), 'text' ),
|
||||
'hero_secondary_url' => array( 'hero', __( 'Botão secundário — link', 'gustavoo-portfolio' ), 'link' ),
|
||||
'about_eyebrow' => array( 'about', __( 'Sobretítulo', 'gustavoo-portfolio' ), 'text' ),
|
||||
'about_title' => array( 'about', __( 'Título', 'gustavoo-portfolio' ), 'text' ),
|
||||
'about_text' => array( 'about', __( 'Texto principal', 'gustavoo-portfolio' ), 'textarea' ),
|
||||
'about_secondary_text' => array( 'about', __( 'Texto complementar', 'gustavoo-portfolio' ), 'textarea' ),
|
||||
'services_eyebrow' => array( 'services', __( 'Sobretítulo', 'gustavoo-portfolio' ), 'text' ),
|
||||
'services_title' => array( 'services', __( 'Título', 'gustavoo-portfolio' ), 'text' ),
|
||||
'services_description' => array( 'services', __( 'Descrição', 'gustavoo-portfolio' ), 'textarea' ),
|
||||
'projects_eyebrow' => array( 'projects', __( 'Sobretítulo', 'gustavoo-portfolio' ), 'text' ),
|
||||
'projects_title' => array( 'projects', __( 'Título', 'gustavoo-portfolio' ), 'text' ),
|
||||
'projects_text' => array( 'projects', __( 'Descrição', 'gustavoo-portfolio' ), 'textarea' ),
|
||||
'projects_limit' => array( 'projects', __( 'Quantidade de projetos', 'gustavoo-portfolio' ), 'number' ),
|
||||
'blog_eyebrow' => array( 'blog', __( 'Sobretítulo', 'gustavoo-portfolio' ), 'text' ),
|
||||
'blog_title' => array( 'blog', __( 'Título', 'gustavoo-portfolio' ), 'text' ),
|
||||
'blog_text' => array( 'blog', __( 'Descrição', 'gustavoo-portfolio' ), 'textarea' ),
|
||||
'blog_limit' => array( 'blog', __( 'Quantidade de posts', 'gustavoo-portfolio' ), 'number' ),
|
||||
'contact_eyebrow' => array( 'contact', __( 'Sobretítulo', 'gustavoo-portfolio' ), 'text' ),
|
||||
'contact_heading' => array( 'contact', __( 'Título', 'gustavoo-portfolio' ), 'text' ),
|
||||
'contact_text' => array( 'contact', __( 'Descrição', 'gustavoo-portfolio' ), 'textarea' ),
|
||||
'email' => array( 'contact', __( 'E-mail', 'gustavoo-portfolio' ), 'email' ),
|
||||
'whatsapp' => array( 'contact', __( 'WhatsApp — número', 'gustavoo-portfolio' ), 'text' ),
|
||||
'whatsapp_message' => array( 'contact', __( 'WhatsApp — mensagem inicial', 'gustavoo-portfolio' ), 'textarea' ),
|
||||
'newsletter_eyebrow' => array( 'newsletter', __( 'Sobretítulo', 'gustavoo-portfolio' ), 'text' ),
|
||||
'newsletter_heading' => array( 'newsletter', __( 'Título', 'gustavoo-portfolio' ), 'text' ),
|
||||
'newsletter_text' => array( 'newsletter', __( 'Descrição', 'gustavoo-portfolio' ), 'textarea' ),
|
||||
'github_url' => array( 'social', __( 'GitHub', 'gustavoo-portfolio' ), 'url' ),
|
||||
'linkedin_url' => array( 'social', __( 'LinkedIn', 'gustavoo-portfolio' ), 'url' ),
|
||||
'instagram_url' => array( 'social', __( 'Instagram', 'gustavoo-portfolio' ), 'url' ),
|
||||
'availability_label' => array( 'social', __( 'Status de disponibilidade', 'gustavoo-portfolio' ), 'text' ),
|
||||
);
|
||||
|
||||
foreach ( $fields as $key => $field ) {
|
||||
$setting_id = 'gustavoo_portfolio_' . $key;
|
||||
$sanitize = 'textarea' === $field[2] ? 'sanitize_textarea_field' : ( 'number' === $field[2] ? 'absint' : ( in_array( $field[2], array( 'url', 'link' ), true ) ? 'gustavoo_portfolio_customize_link' : ( 'email' === $field[2] ? 'sanitize_email' : 'sanitize_text_field' ) ) );
|
||||
|
||||
$wp_customize->add_setting(
|
||||
$setting_id,
|
||||
array(
|
||||
'default' => gustavoo_portfolio_get_setting( $key ),
|
||||
'sanitize_callback' => $sanitize,
|
||||
// Each front-page section is refreshed by its native Customizer
|
||||
// partial, allowing WordPress to expose its own edit shortcut.
|
||||
'transport' => 'postMessage',
|
||||
)
|
||||
);
|
||||
|
||||
$control_args = array(
|
||||
'label' => $field[1],
|
||||
'section' => 'gustavoo_portfolio_' . $field[0],
|
||||
'type' => in_array( $field[2], array( 'textarea', 'number', 'email', 'url' ), true ) ? $field[2] : 'text',
|
||||
);
|
||||
|
||||
if ( 'number' === $field[2] ) {
|
||||
$control_args['input_attrs'] = array( 'min' => 1, 'max' => 24 );
|
||||
}
|
||||
|
||||
$wp_customize->add_control( $setting_id, $control_args );
|
||||
}
|
||||
|
||||
if ( ! isset( $wp_customize->selective_refresh ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$partials = array(
|
||||
'hero' => array( '.hero-stage', 'template-parts/front/hero', array( 'hero_eyebrow', 'hero_title', 'hero_description', 'hero_primary_label', 'hero_primary_url', 'hero_secondary_label', 'hero_secondary_url' ) ),
|
||||
'about' => array( '#sobre', 'template-parts/front/about', array( 'about_eyebrow', 'about_title', 'about_text', 'about_secondary_text' ) ),
|
||||
'services' => array( '#servicos', 'template-parts/front/services', array( 'services_eyebrow', 'services_title', 'services_description' ) ),
|
||||
'projects' => array( '#projetos', 'template-parts/front/projects', array( 'projects_eyebrow', 'projects_title', 'projects_text', 'projects_limit' ) ),
|
||||
'blog' => array( '#blog', 'template-parts/front/posts', array( 'blog_eyebrow', 'blog_title', 'blog_text', 'blog_limit' ) ),
|
||||
'contact' => array( '#contato', 'template-parts/front/contact', array( 'contact_eyebrow', 'contact_heading', 'contact_text', 'email', 'whatsapp', 'whatsapp_message', 'github_url', 'linkedin_url', 'instagram_url' ) ),
|
||||
);
|
||||
|
||||
foreach ( $partials as $id => $partial ) {
|
||||
$settings = array_map(
|
||||
static function ( $key ) {
|
||||
return 'gustavoo_portfolio_' . $key;
|
||||
},
|
||||
$partial[2]
|
||||
);
|
||||
|
||||
/*
|
||||
* A native edit shortcut is tied to the partial's primary setting.
|
||||
* Using the first actual setting as the partial ID makes the pencil
|
||||
* focus a real control instead of an unresolvable synthetic partial.
|
||||
*/
|
||||
$wp_customize->selective_refresh->add_partial(
|
||||
$settings[0],
|
||||
array(
|
||||
'selector' => $partial[0],
|
||||
'settings' => $settings,
|
||||
'primary_setting' => $settings[0],
|
||||
'container_inclusive' => true,
|
||||
'render_callback' => static function () use ( $partial ) {
|
||||
return gustavoo_portfolio_customize_render_part( $partial[1] );
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
$wp_customize->selective_refresh->add_partial(
|
||||
'gustavoo_portfolio_whatsapp_shortcut',
|
||||
array(
|
||||
'selector' => '.whatsapp-float-wrap',
|
||||
'settings' => array( 'gustavoo_portfolio_whatsapp', 'gustavoo_portfolio_whatsapp_message' ),
|
||||
'primary_setting' => 'gustavoo_portfolio_whatsapp',
|
||||
'container_inclusive' => true,
|
||||
'render_callback' => static function () {
|
||||
return gustavoo_portfolio_customize_render_part( 'template-parts/global/whatsapp-float' );
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
add_action( 'customize_register', 'gustavoo_portfolio_customize_register' );
|
||||
|
||||
/** Register native Customizer shortcuts for the theme's menu locations. */
|
||||
function gustavoo_portfolio_customize_menu_shortcuts( $wp_customize ) {
|
||||
if ( ! isset( $wp_customize->selective_refresh ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$menus = array(
|
||||
'primary' => '#site-navigation',
|
||||
'news_categories' => '.news-category-nav',
|
||||
);
|
||||
|
||||
foreach ( $menus as $location => $selector ) {
|
||||
$setting = 'nav_menu_locations[' . $location . ']';
|
||||
|
||||
if ( ! $wp_customize->get_setting( $setting ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$wp_customize->selective_refresh->add_partial(
|
||||
'gustavoo_portfolio_menu_shortcut_' . $location,
|
||||
array(
|
||||
'selector' => $selector,
|
||||
'settings' => array( $setting ),
|
||||
'primary_setting' => $setting,
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
add_action( 'customize_register', 'gustavoo_portfolio_customize_menu_shortcuts', 20 );
|
||||
@@ -0,0 +1,173 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme setting defaults and reusable portfolio content.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return default settings without writing options to the database.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
function gustavoo_portfolio_get_defaults() {
|
||||
$defaults = array(
|
||||
'hero_eyebrow' => __( 'Desenvolvimento de ponta a ponta', 'gustavoo-portfolio' ),
|
||||
'hero_title' => __( 'Transformo ideias em produtos digitais sólidos.', 'gustavoo-portfolio' ),
|
||||
'hero_description' => __( 'Gustavo, Desenvolvedor Full Stack Sênior. Web, mobile, infraestrutura e automação para tirar projetos do papel e fazê-los crescer.', 'gustavoo-portfolio' ),
|
||||
'hero_primary_label' => __( 'Ver projetos', 'gustavoo-portfolio' ),
|
||||
'hero_primary_url' => '#projetos',
|
||||
'hero_secondary_label' => __( 'Fale comigo', 'gustavoo-portfolio' ),
|
||||
'hero_secondary_url' => '#contato',
|
||||
'about_eyebrow' => __( 'Sobre mim', 'gustavoo-portfolio' ),
|
||||
'about_title' => __( 'Responsabilidade técnica do planejamento à produção.', 'gustavoo-portfolio' ),
|
||||
'about_text' => __( 'Mais do que escrever código, meu objetivo é garantir que seu projeto saia do papel e funcione exatamente como planejado. Assumo a responsabilidade técnica de ponta a ponta para que você foque no que importa: crescer.', 'gustavoo-portfolio' ),
|
||||
'about_secondary_text' => __( 'Já participei do desenvolvimento e lançamento de múltiplos projetos digitais, atuando da arquitetura técnica à divulgação e ao crescimento das plataformas. Essa combinação de visão técnica e entendimento de mercado orienta cada entrega.', 'gustavoo-portfolio' ),
|
||||
'services_eyebrow' => __( 'Como posso ajudar', 'gustavoo-portfolio' ),
|
||||
'services_title' => __( 'Soluções completas para produtos digitais.', 'gustavoo-portfolio' ),
|
||||
'services_description' => __( 'Estratégia, código e infraestrutura trabalhando juntos para criar experiências rápidas, seguras e preparadas para evoluir.', 'gustavoo-portfolio' ),
|
||||
'projects_eyebrow' => __( 'Portfólio', 'gustavoo-portfolio' ),
|
||||
'projects_title' => __( 'Projetos selecionados', 'gustavoo-portfolio' ),
|
||||
'projects_text' => __( 'Uma seleção de produtos, experiências e soluções que ajudei a colocar no mundo.', 'gustavoo-portfolio' ),
|
||||
'projects_limit' => 6,
|
||||
'blog_eyebrow' => __( 'Blog', 'gustavoo-portfolio' ),
|
||||
'blog_title' => __( 'Código, produto e bastidores', 'gustavoo-portfolio' ),
|
||||
'blog_text' => __( 'Análises práticas sobre desenvolvimento, infraestrutura, automação e crescimento de produtos digitais.', 'gustavoo-portfolio' ),
|
||||
'blog_limit' => 4,
|
||||
'contact_eyebrow' => __( 'Vamos conversar', 'gustavoo-portfolio' ),
|
||||
'contact_heading' => __( 'Tem um projeto em mente?', 'gustavoo-portfolio' ),
|
||||
'contact_text' => __( 'Conte o que você precisa construir ou melhorar. Responderei com os próximos passos para transformar a ideia em uma entrega concreta.', 'gustavoo-portfolio' ),
|
||||
'contact_form_id' => 0,
|
||||
'newsletter_eyebrow' => __( 'Newsletter', 'gustavoo-portfolio' ),
|
||||
'newsletter_heading' => __( 'Ideias úteis, direto na sua caixa de entrada.', 'gustavoo-portfolio' ),
|
||||
'newsletter_text' => __( 'Receba conteúdos sobre desenvolvimento, produto, infraestrutura e automação. Sem ruído e sem spam.', 'gustavoo-portfolio' ),
|
||||
'newsletter_form_id' => 0,
|
||||
'email' => (string) get_option( 'admin_email', '' ),
|
||||
'whatsapp' => '',
|
||||
'whatsapp_message' => __( 'Olá! Gostaria de falar sobre um projeto.', 'gustavoo-portfolio' ),
|
||||
'github_url' => '',
|
||||
'linkedin_url' => '',
|
||||
'instagram_url' => '',
|
||||
'projects_archive_url' => '',
|
||||
'availability_label' => __( 'Disponível para novos projetos', 'gustavoo-portfolio' ),
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter theme defaults before saved settings are merged.
|
||||
*
|
||||
* @param array<string, mixed> $defaults Default settings.
|
||||
*/
|
||||
return apply_filters( 'gustavoo_portfolio_defaults', $defaults );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the saved theme settings merged with safe local defaults.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
function gustavoo_portfolio_get_settings() {
|
||||
$settings = get_option( 'gustavoo_portfolio_settings', array() );
|
||||
|
||||
if ( ! is_array( $settings ) ) {
|
||||
$settings = array();
|
||||
}
|
||||
|
||||
return wp_parse_args( $settings, gustavoo_portfolio_get_defaults() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Read one theme setting. A few aliases preserve compatibility with early builds.
|
||||
*
|
||||
* @param string $key Setting key.
|
||||
* @param mixed $fallback Optional fallback.
|
||||
* @return mixed
|
||||
*/
|
||||
function gustavoo_portfolio_get_setting( $key, $fallback = null ) {
|
||||
$customizer_key = 'gustavoo_portfolio_' . $key;
|
||||
$customizer_values = get_theme_mods();
|
||||
|
||||
if ( is_array( $customizer_values ) && array_key_exists( $customizer_key, $customizer_values ) ) {
|
||||
return $customizer_values[ $customizer_key ];
|
||||
}
|
||||
|
||||
$settings = gustavoo_portfolio_get_settings();
|
||||
$aliases = array(
|
||||
'hero_eyebrow' => array( 'hero_kicker' ),
|
||||
'hero_description' => array( 'hero_text' ),
|
||||
'contact_form_id' => array( 'fluent_contact_form_id', 'lead_form_id' ),
|
||||
'newsletter_form_id' => array( 'fluent_newsletter_form_id', 'fluentcrm_form_id' ),
|
||||
'contact_heading' => array( 'contact_title' ),
|
||||
'newsletter_heading' => array( 'newsletter_title' ),
|
||||
);
|
||||
|
||||
if ( array_key_exists( $key, $settings ) && '' !== $settings[ $key ] && null !== $settings[ $key ] ) {
|
||||
return $settings[ $key ];
|
||||
}
|
||||
|
||||
if ( isset( $aliases[ $key ] ) ) {
|
||||
foreach ( $aliases[ $key ] as $alias ) {
|
||||
if ( array_key_exists( $alias, $settings ) && '' !== $settings[ $alias ] && null !== $settings[ $alias ] ) {
|
||||
return $settings[ $alias ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( null !== $fallback ) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
$defaults = gustavoo_portfolio_get_defaults();
|
||||
|
||||
return $defaults[ $key ] ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the service cards used by the front page.
|
||||
*
|
||||
* @return array<int, array<string, string>>
|
||||
*/
|
||||
function gustavoo_portfolio_get_services() {
|
||||
$services = array(
|
||||
array(
|
||||
'number' => '01',
|
||||
'title' => __( 'Web, Mobile e E-commerce', 'gustavoo-portfolio' ),
|
||||
'description' => __( 'Sites institucionais, aplicações para iOS e Android, softwares desktop, lojas e marketplaces personalizados com foco em experiência e conversão.', 'gustavoo-portfolio' ),
|
||||
),
|
||||
array(
|
||||
'number' => '02',
|
||||
'title' => __( 'WordPress avançado', 'gustavoo-portfolio' ),
|
||||
'description' => __( 'Temas e plugins sob medida, integrações específicas, recuperação de sites e otimização para Core Web Vitals.', 'gustavoo-portfolio' ),
|
||||
),
|
||||
array(
|
||||
'number' => '03',
|
||||
'title' => __( 'Infraestrutura e servidores', 'gustavoo-portfolio' ),
|
||||
'description' => __( 'Ambientes Linux, VPS e servidores dedicados configurados para manter aplicações estáveis, rápidas, seguras e escaláveis.', 'gustavoo-portfolio' ),
|
||||
),
|
||||
array(
|
||||
'number' => '04',
|
||||
'title' => __( 'Automação e integrações', 'gustavoo-portfolio' ),
|
||||
'description' => __( 'APIs e fluxos com n8n para conectar sistemas, organizar dados e eliminar tarefas operacionais repetitivas.', 'gustavoo-portfolio' ),
|
||||
),
|
||||
array(
|
||||
'number' => '05',
|
||||
'title' => __( 'Games e experiências interativas', 'gustavoo-portfolio' ),
|
||||
'description' => __( 'Jogos 2D e 3D para celulares, computadores e navegadores, incluindo ranking, multiplayer e compras dentro do jogo.', 'gustavoo-portfolio' ),
|
||||
),
|
||||
array(
|
||||
'number' => '06',
|
||||
'title' => __( 'Divulgação e crescimento', 'gustavoo-portfolio' ),
|
||||
'description' => __( 'Estratégias de conteúdo, comunidades, parcerias e mídia paga para aproximar produtos digitais do público certo.', 'gustavoo-portfolio' ),
|
||||
),
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter the service cards shown on the front page.
|
||||
*
|
||||
* @param array<int, array<string, string>> $services Service cards.
|
||||
*/
|
||||
return apply_filters( 'gustavoo_portfolio_services', $services );
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?php
|
||||
/**
|
||||
* Front-end assets.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a cache-busting asset version.
|
||||
*
|
||||
* @param string $relative_path Theme-relative path.
|
||||
* @return string
|
||||
*/
|
||||
function gustavoo_portfolio_asset_version( $relative_path ) {
|
||||
$release = '1.1.0';
|
||||
$path = get_theme_file_path( '/' . ltrim( $relative_path, '/' ) );
|
||||
|
||||
if ( file_exists( $path ) ) {
|
||||
return $release . '-' . (string) filemtime( $path );
|
||||
}
|
||||
|
||||
return $release;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enqueue only local, versioned assets.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_enqueue_assets() {
|
||||
wp_enqueue_style(
|
||||
'gustavoo-portfolio-style',
|
||||
get_stylesheet_uri(),
|
||||
array(),
|
||||
gustavoo_portfolio_asset_version( 'style.css' )
|
||||
);
|
||||
|
||||
if ( file_exists( get_theme_file_path( '/assets/css/main.css' ) ) ) {
|
||||
wp_enqueue_style(
|
||||
'gustavoo-portfolio-main',
|
||||
get_theme_file_uri( '/assets/css/main.css' ),
|
||||
array( 'gustavoo-portfolio-style' ),
|
||||
gustavoo_portfolio_asset_version( 'assets/css/main.css' )
|
||||
);
|
||||
}
|
||||
|
||||
if ( file_exists( get_theme_file_path( '/assets/js/navigation.js' ) ) ) {
|
||||
wp_enqueue_script(
|
||||
'gustavoo-portfolio-navigation',
|
||||
get_theme_file_uri( '/assets/js/navigation.js' ),
|
||||
array(),
|
||||
gustavoo_portfolio_asset_version( 'assets/js/navigation.js' ),
|
||||
true
|
||||
);
|
||||
|
||||
wp_script_add_data( 'gustavoo-portfolio-navigation', 'strategy', 'defer' );
|
||||
wp_localize_script(
|
||||
'gustavoo-portfolio-navigation',
|
||||
'gustavooPortfolioNavigation',
|
||||
array(
|
||||
'expand' => __( 'Abrir menu', 'gustavoo-portfolio' ),
|
||||
'collapse' => __( 'Fechar menu', 'gustavoo-portfolio' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
if ( is_singular() && comments_open() && get_option( 'thread_comments' ) ) {
|
||||
wp_enqueue_script( 'comment-reply' );
|
||||
}
|
||||
}
|
||||
add_action( 'wp_enqueue_scripts', 'gustavoo_portfolio_enqueue_assets' );
|
||||
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
/**
|
||||
* Fluent Forms presentation helpers.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure the configured contact form contains the fields required by the site.
|
||||
*
|
||||
* This is intentionally idempotent so forms created by an older seed version
|
||||
* are repaired even when the seeder state is already marked complete.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_ensure_contact_form_fields() {
|
||||
$form_id = absint( gustavoo_portfolio_get_setting( 'contact_form_id' ) );
|
||||
|
||||
if ( ! $form_id || ! class_exists( '\FluentForm\App\Models\Form' ) || ! function_exists( 'fluentformLoadFile' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$form = \FluentForm\App\Models\Form::find( $form_id );
|
||||
|
||||
if ( ! $form ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$structure = json_decode( (string) $form->form_fields, true );
|
||||
|
||||
if ( ! is_array( $structure ) || ! isset( $structure['fields'] ) || ! is_array( $structure['fields'] ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$defaults = fluentformLoadFile( 'Services/FormBuilder/DefaultElements.php' );
|
||||
$message = $defaults['general']['textarea'] ?? array();
|
||||
|
||||
if ( ! $message ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fields_by_name = array();
|
||||
$changed = false;
|
||||
|
||||
foreach ( $structure['fields'] as $field ) {
|
||||
$name = (string) ( $field['attributes']['name'] ?? '' );
|
||||
|
||||
if ( ! in_array( $name, array( 'email', 'whatsapp', 'message' ), true ) ) {
|
||||
$changed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ( isset( $fields_by_name[ $name ] ) ) {
|
||||
$changed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
$fields_by_name[ $name ] = $field;
|
||||
}
|
||||
|
||||
if ( isset( $fields_by_name['email'] ) ) {
|
||||
$fields_by_name['email']['settings']['validation_rules']['required']['value'] = true;
|
||||
}
|
||||
|
||||
if ( isset( $fields_by_name['whatsapp'] ) ) {
|
||||
$whatsapp = $fields_by_name['whatsapp'];
|
||||
$whatsapp['settings']['validation_rules']['required']['value'] = true;
|
||||
$whatsapp['settings']['temp_mask'] = 'custom';
|
||||
$whatsapp['settings']['data-mask-reverse'] = 'no';
|
||||
$whatsapp['attributes']['data-mask'] = '(00) 00000-0000';
|
||||
$fields_by_name['whatsapp'] = $whatsapp;
|
||||
}
|
||||
|
||||
if ( ! isset( $fields_by_name['whatsapp'] ) ) {
|
||||
$whatsapp = $defaults['general']['input_mask'] ?? array();
|
||||
if ( $whatsapp ) {
|
||||
$whatsapp['uniqElKey'] = 'el_gso_contact_whatsapp';
|
||||
$whatsapp['attributes']['name'] = 'whatsapp';
|
||||
$whatsapp['attributes']['placeholder'] = '(31) 99999-9999';
|
||||
$whatsapp['attributes']['data-mask'] = '(00) 00000-0000';
|
||||
$whatsapp['settings']['label'] = __( 'WhatsApp', 'gustavoo-portfolio' );
|
||||
$whatsapp['settings']['admin_field_label'] = __( 'WhatsApp', 'gustavoo-portfolio' );
|
||||
$whatsapp['settings']['mobile_keyboard_type'] = 'tel';
|
||||
$whatsapp['settings']['temp_mask'] = 'custom';
|
||||
$whatsapp['settings']['data-mask-reverse'] = 'no';
|
||||
$whatsapp['settings']['validation_rules']['required']['value'] = true;
|
||||
$fields_by_name['whatsapp'] = $whatsapp;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! isset( $fields_by_name['message'] ) || 'textarea' !== (string) ( $fields_by_name['message']['element'] ?? '' ) ) {
|
||||
$message['uniqElKey'] = 'el_gso_contact_message';
|
||||
$message['attributes']['name'] = 'message';
|
||||
$message['attributes']['placeholder'] = __( 'Descreva o motivo do contato e o que você quer construir.', 'gustavoo-portfolio' );
|
||||
$message['attributes']['rows'] = 5;
|
||||
$message['settings']['label'] = __( 'Como posso ajudar?', 'gustavoo-portfolio' );
|
||||
$message['settings']['admin_field_label'] = __( 'Motivo do contato', 'gustavoo-portfolio' );
|
||||
$message['settings']['validation_rules']['required']['value'] = true;
|
||||
$fields_by_name['message'] = $message;
|
||||
}
|
||||
|
||||
$fields = array();
|
||||
foreach ( array( 'email', 'whatsapp', 'message' ) as $required_name ) {
|
||||
if ( isset( $fields_by_name[ $required_name ] ) ) {
|
||||
$fields[] = $fields_by_name[ $required_name ];
|
||||
}
|
||||
}
|
||||
$changed = wp_json_encode( $structure['fields'] ) !== wp_json_encode( $fields );
|
||||
|
||||
if ( ! $changed ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$structure['fields'] = $fields;
|
||||
$form_fields = wp_json_encode( $structure, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES );
|
||||
|
||||
if ( class_exists( '\FluentForm\App\Services\Form\FormService' ) ) {
|
||||
( new \FluentForm\App\Services\Form\FormService() )->update(
|
||||
array(
|
||||
'form_id' => $form->id,
|
||||
'title' => $form->title,
|
||||
'status' => $form->status,
|
||||
'formFields' => $form_fields,
|
||||
)
|
||||
);
|
||||
} else {
|
||||
$form->form_fields = $form_fields;
|
||||
$form->save();
|
||||
}
|
||||
}
|
||||
add_action( 'init', 'gustavoo_portfolio_ensure_contact_form_fields', 30 );
|
||||
|
||||
/**
|
||||
* Preserve contact fields in submissions while an older form schema is being
|
||||
* migrated. Fluent Forms only whitelists fields known by its saved schema.
|
||||
*
|
||||
* @param array $form_data Sanitized submission data.
|
||||
* @param int $form_id Submitted form ID.
|
||||
* @param array $input_configs Fluent Forms input configuration.
|
||||
* @return array
|
||||
*/
|
||||
function gustavoo_portfolio_preserve_contact_submission_fields( $form_data, $form_id, $input_configs ) {
|
||||
$contact_form_id = absint( gustavoo_portfolio_get_setting( 'contact_form_id' ) );
|
||||
|
||||
if ( ! $contact_form_id || $contact_form_id !== absint( $form_id ) ) {
|
||||
return $form_data;
|
||||
}
|
||||
|
||||
if ( isset( $_POST['whatsapp'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Fluent Forms validates the submission.
|
||||
$form_data['whatsapp'] = sanitize_text_field( wp_unslash( $_POST['whatsapp'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
}
|
||||
|
||||
if ( isset( $_POST['message'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing -- Fluent Forms validates the submission.
|
||||
$form_data['message'] = sanitize_textarea_field( wp_unslash( $_POST['message'] ) ); // phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||||
}
|
||||
|
||||
return $form_data;
|
||||
}
|
||||
add_filter( 'fluentform/insert_response_data', 'gustavoo_portfolio_preserve_contact_submission_fields', 10, 3 );
|
||||
|
||||
/**
|
||||
* Render a Fluent Forms form from a numeric, administrator-controlled ID.
|
||||
*
|
||||
* The theme deliberately never stores or executes arbitrary shortcodes. Contact
|
||||
* synchronization is configured through the FluentCRM feed inside Fluent Forms.
|
||||
*
|
||||
* @param int $form_id Form ID.
|
||||
* @param string $context Form context, used for classes and filters.
|
||||
* @return string
|
||||
*/
|
||||
function gustavoo_portfolio_render_fluent_form( $form_id, $context = 'default' ) {
|
||||
$form_id = absint( $form_id );
|
||||
$context = sanitize_html_class( $context );
|
||||
|
||||
if ( $form_id && shortcode_exists( 'fluentform' ) ) {
|
||||
if ( 'contact' === $context ) {
|
||||
gustavoo_portfolio_ensure_contact_form_fields();
|
||||
}
|
||||
|
||||
$shortcode = sprintf( '[fluentform id="%d"]', $form_id );
|
||||
$markup = do_shortcode( $shortcode );
|
||||
|
||||
// Older persisted forms may still contain only the e-mail field. Keep the
|
||||
// requested fields visible inside the real Fluent Forms <form>.
|
||||
if ( 'contact' === $context && false !== stripos( $markup, '</form>' ) ) {
|
||||
$missing_fields = '';
|
||||
|
||||
if ( false === stripos( $markup, 'name="whatsapp"' ) ) {
|
||||
$missing_fields .= '<div class="ff-el-group"><div class="ff-el-input--label"><label for="gso-contact-whatsapp">' . esc_html__( 'WhatsApp', 'gustavoo-portfolio' ) . '</label></div><div class="ff-el-input--content"><input id="gso-contact-whatsapp" name="whatsapp" class="ff-el-form-control" type="tel" placeholder="(31) 99999-9999" inputmode="tel" data-mask="(00) 00000-0000" data-mask-reverse="false"></div></div>';
|
||||
}
|
||||
|
||||
if ( false === stripos( $markup, 'name="message"' ) ) {
|
||||
$missing_fields .= '<div class="ff-el-group"><div class="ff-el-input--label"><label for="gso-contact-message">' . esc_html__( 'Como posso ajudar?', 'gustavoo-portfolio' ) . '</label></div><div class="ff-el-input--content"><textarea id="gso-contact-message" name="message" class="ff-el-form-control" rows="5" placeholder="' . esc_attr__( 'Descreva o motivo do contato e o que você quer construir.', 'gustavoo-portfolio' ) . '"></textarea></div></div>';
|
||||
}
|
||||
|
||||
if ( $missing_fields ) {
|
||||
$markup = preg_replace( '#<button\b#i', $missing_fields . '<button', $markup, 1 );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter trusted Fluent Forms output before it is returned.
|
||||
*
|
||||
* @param string $markup Form markup generated by Fluent Forms.
|
||||
* @param int $form_id Form ID.
|
||||
* @param string $context Presentation context.
|
||||
*/
|
||||
return (string) apply_filters( 'gustavoo_portfolio_fluent_form_markup', $markup, $form_id, $context );
|
||||
}
|
||||
|
||||
$email = sanitize_email( (string) gustavoo_portfolio_get_setting( 'email' ) );
|
||||
$contact_url = gustavoo_portfolio_section_url( 'contato' );
|
||||
$button_url = $email ? 'mailto:' . $email : $contact_url;
|
||||
$button_label = 'newsletter' === $context
|
||||
? __( 'Quero receber novidades', 'gustavoo-portfolio' )
|
||||
: __( 'Enviar uma mensagem', 'gustavoo-portfolio' );
|
||||
|
||||
$fallback = '<div class="form-fallback form-fallback--' . esc_attr( $context ) . '">';
|
||||
$fallback .= '<p>' . esc_html__( 'O formulário está sendo configurado. Você ainda pode entrar em contato diretamente.', 'gustavoo-portfolio' ) . '</p>';
|
||||
$fallback .= '<a class="button button--primary" href="' . esc_url( $button_url ) . '">' . esc_html( $button_label ) . '</a>';
|
||||
|
||||
if ( current_user_can( 'manage_options' ) ) {
|
||||
$fallback .= '<p class="form-fallback__admin"><a href="' . esc_url( admin_url( 'edit.php?post_type=gso_project&page=gso-portfolio-settings' ) ) . '">';
|
||||
$fallback .= esc_html__( 'Configure o ID do Fluent Forms nas opções do portfólio.', 'gustavoo-portfolio' );
|
||||
$fallback .= '</a></p>';
|
||||
}
|
||||
|
||||
$fallback .= '</div>';
|
||||
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print a Fluent Forms form. Output originates either from the trusted plugin
|
||||
* shortcode or from fully escaped fallback markup built above.
|
||||
*
|
||||
* @param int $form_id Form ID.
|
||||
* @param string $context Form context.
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_the_fluent_form( $form_id, $context = 'default' ) {
|
||||
echo gustavoo_portfolio_render_fluent_form( $form_id, $context ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Trusted plugin output or escaped local fallback.
|
||||
}
|
||||
@@ -0,0 +1,146 @@
|
||||
<?php
|
||||
/**
|
||||
* Theme setup and core WordPress integrations.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register theme supports, menus, and editor features.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_setup() {
|
||||
load_theme_textdomain( 'gustavoo-portfolio', get_template_directory() . '/languages' );
|
||||
|
||||
add_theme_support( 'automatic-feed-links' );
|
||||
add_theme_support( 'title-tag' );
|
||||
add_theme_support( 'post-thumbnails' );
|
||||
add_theme_support( 'responsive-embeds' );
|
||||
add_theme_support( 'align-wide' );
|
||||
add_theme_support( 'editor-styles' );
|
||||
add_editor_style( 'assets/css/editor.css' );
|
||||
|
||||
add_theme_support(
|
||||
'html5',
|
||||
array(
|
||||
'comment-form',
|
||||
'comment-list',
|
||||
'gallery',
|
||||
'caption',
|
||||
'script',
|
||||
'search-form',
|
||||
'style',
|
||||
)
|
||||
);
|
||||
|
||||
add_theme_support(
|
||||
'custom-logo',
|
||||
array(
|
||||
'height' => 160,
|
||||
'width' => 160,
|
||||
'flex-height' => true,
|
||||
'flex-width' => true,
|
||||
)
|
||||
);
|
||||
|
||||
register_nav_menus(
|
||||
array(
|
||||
'primary' => __( 'Menu principal', 'gustavoo-portfolio' ),
|
||||
'news_categories' => __( 'Menu de categorias de notícias', 'gustavoo-portfolio' ),
|
||||
'footer' => __( 'Menu do rodapé', 'gustavoo-portfolio' ),
|
||||
)
|
||||
);
|
||||
|
||||
add_image_size( 'gustavoo-project-card', 720, 480, true );
|
||||
add_image_size( 'gustavoo-post-card', 720, 460, true );
|
||||
}
|
||||
add_action( 'after_setup_theme', 'gustavoo_portfolio_setup' );
|
||||
|
||||
/**
|
||||
* Define a comfortable content width for embeds and media.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_content_width() {
|
||||
$GLOBALS['content_width'] = apply_filters( 'gustavoo_portfolio_content_width', 780 );
|
||||
}
|
||||
add_action( 'after_setup_theme', 'gustavoo_portfolio_content_width', 0 );
|
||||
|
||||
/**
|
||||
* Add useful state classes without coupling templates to presentation logic.
|
||||
*
|
||||
* @param string[] $classes Existing body classes.
|
||||
* @return string[]
|
||||
*/
|
||||
function gustavoo_portfolio_body_classes( $classes ) {
|
||||
if ( is_front_page() ) {
|
||||
$classes[] = 'has-overlay-header';
|
||||
}
|
||||
|
||||
if ( ! is_front_page() && is_active_sidebar( 'sidebar-blog' ) ) {
|
||||
$classes[] = 'has-blog-sidebar';
|
||||
}
|
||||
|
||||
if ( ! is_singular() ) {
|
||||
$classes[] = 'is-list-view';
|
||||
}
|
||||
|
||||
return array_unique( $classes );
|
||||
}
|
||||
add_filter( 'body_class', 'gustavoo_portfolio_body_classes' );
|
||||
|
||||
/** Set the posts page browser title to the editorial section name. */
|
||||
function gustavoo_portfolio_blog_document_title( $title ) {
|
||||
if ( is_home() ) {
|
||||
$title['title'] = __( 'Últimas notícias', 'gustavoo-portfolio' );
|
||||
}
|
||||
|
||||
return $title;
|
||||
}
|
||||
add_filter( 'document_title_parts', 'gustavoo_portfolio_blog_document_title' );
|
||||
|
||||
/** Keep the editorial top grid focused on the five newest posts. */
|
||||
function gustavoo_portfolio_news_posts_per_page( $query ) {
|
||||
if ( is_admin() || ! $query->is_main_query() || ! ( $query->is_home() || $query->is_category() ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$query->set( 'posts_per_page', 5 );
|
||||
}
|
||||
add_action( 'pre_get_posts', 'gustavoo_portfolio_news_posts_per_page' );
|
||||
|
||||
/** Refresh category rewrite rules once after the editorial templates are installed. */
|
||||
function gustavoo_portfolio_refresh_editorial_rewrites() {
|
||||
$version = '1.0.0';
|
||||
|
||||
if ( $version === get_option( 'gustavoo_portfolio_editorial_rewrite_version' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
flush_rewrite_rules( false );
|
||||
update_option( 'gustavoo_portfolio_editorial_rewrite_version', $version, false );
|
||||
}
|
||||
add_action( 'init', 'gustavoo_portfolio_refresh_editorial_rewrites', 99 );
|
||||
|
||||
/**
|
||||
* Print a fallback icon only when WordPress has no configured Site Icon.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_fallback_site_icon() {
|
||||
if ( has_site_icon() || ! function_exists( 'gustavoo_portfolio_get_image_source' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$icon_url = gustavoo_portfolio_get_image_source( 'logo-mark', 'png' );
|
||||
|
||||
if ( $icon_url ) {
|
||||
printf( '<link rel="icon" href="%s" sizes="192x192">' . "\n", esc_url( $icon_url ) );
|
||||
}
|
||||
}
|
||||
add_action( 'wp_head', 'gustavoo_portfolio_fallback_site_icon', 2 );
|
||||
@@ -0,0 +1,569 @@
|
||||
<?php
|
||||
/**
|
||||
* Reusable template helpers.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve an image source, preferring an existing format and falling back safely.
|
||||
*
|
||||
* @param string $basename File basename without extension.
|
||||
* @param string $preferred Preferred extension.
|
||||
* @return string
|
||||
*/
|
||||
function gustavoo_portfolio_get_image_source( $basename, $preferred = 'webp' ) {
|
||||
$basename = preg_replace( '/[^a-z0-9-]/', '', strtolower( (string) $basename ) );
|
||||
$preferred = in_array( $preferred, array( 'webp', 'png' ), true ) ? $preferred : 'webp';
|
||||
$formats = array_unique( array( $preferred, 'webp', 'png' ) );
|
||||
|
||||
if ( ! $basename ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
foreach ( $formats as $format ) {
|
||||
$relative_path = '/assets/images/' . $basename . '.' . $format;
|
||||
|
||||
if ( file_exists( get_theme_file_path( $relative_path ) ) ) {
|
||||
return get_theme_file_uri( $relative_path );
|
||||
}
|
||||
}
|
||||
|
||||
// Keep a deterministic URI while assets are being provisioned by deployment.
|
||||
return get_theme_file_uri( '/assets/images/' . $basename . '.' . $preferred );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return image URLs for a picture element.
|
||||
*
|
||||
* @param string $basename File basename without extension.
|
||||
* @return array{webp:string,png:string,fallback:string}
|
||||
*/
|
||||
function gustavoo_portfolio_get_picture_sources( $basename ) {
|
||||
$webp_path = '/assets/images/' . $basename . '.webp';
|
||||
$png_path = '/assets/images/' . $basename . '.png';
|
||||
$has_webp = file_exists( get_theme_file_path( $webp_path ) );
|
||||
$has_png = file_exists( get_theme_file_path( $png_path ) );
|
||||
|
||||
return array(
|
||||
'webp' => $has_webp ? get_theme_file_uri( $webp_path ) : '',
|
||||
'png' => $has_png ? get_theme_file_uri( $png_path ) : '',
|
||||
'fallback' => $has_png ? get_theme_file_uri( $png_path ) : get_theme_file_uri( $webp_path ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the configured logo or the bundled brand mark.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_the_brand() {
|
||||
$site_name = get_bloginfo( 'name' );
|
||||
|
||||
if ( has_custom_logo() ) {
|
||||
echo get_custom_logo(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Core-generated custom logo markup.
|
||||
return;
|
||||
}
|
||||
|
||||
$sources = gustavoo_portfolio_get_picture_sources( 'logo-mark' );
|
||||
?>
|
||||
<a class="custom-logo-link" href="<?php echo esc_url( home_url( '/' ) ); ?>" rel="home">
|
||||
<picture>
|
||||
<?php if ( $sources['webp'] ) : ?>
|
||||
<source srcset="<?php echo esc_url( $sources['webp'] ); ?>" type="image/webp">
|
||||
<?php endif; ?>
|
||||
<img class="custom-logo" src="<?php echo esc_url( $sources['fallback'] ); ?>" width="64" height="64" alt="<?php echo esc_attr( $site_name ); ?>">
|
||||
</picture>
|
||||
</a>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the appropriate URL for a front-page section.
|
||||
*
|
||||
* @param string $section_id Section anchor without hash.
|
||||
* @return string
|
||||
*/
|
||||
function gustavoo_portfolio_section_url( $section_id ) {
|
||||
$section_id = sanitize_html_class( $section_id );
|
||||
|
||||
if ( is_front_page() ) {
|
||||
return '#' . $section_id;
|
||||
}
|
||||
|
||||
return home_url( '/#' . $section_id );
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the configured posts-page URL.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function gustavoo_portfolio_get_blog_url() {
|
||||
$posts_page_id = absint( get_option( 'page_for_posts' ) );
|
||||
|
||||
if ( $posts_page_id ) {
|
||||
$url = get_permalink( $posts_page_id );
|
||||
|
||||
if ( $url ) {
|
||||
return $url;
|
||||
}
|
||||
}
|
||||
|
||||
return home_url( '/blog/' );
|
||||
}
|
||||
|
||||
/** Render the editorial category navigation used on news pages. */
|
||||
function gustavoo_portfolio_news_category_menu() {
|
||||
if ( has_nav_menu( 'news_categories' ) ) {
|
||||
?>
|
||||
<nav class="news-category-nav" aria-label="<?php esc_attr_e( 'Categorias de notícias', 'gustavoo-portfolio' ); ?>">
|
||||
<div class="news-category-nav__inner site-shell">
|
||||
<?php
|
||||
wp_nav_menu(
|
||||
array(
|
||||
'theme_location' => 'news_categories',
|
||||
'menu_class' => 'news-category-nav__list',
|
||||
'container' => false,
|
||||
'fallback_cb' => false,
|
||||
'depth' => 1,
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
</nav>
|
||||
<?php
|
||||
return;
|
||||
}
|
||||
|
||||
$categories = get_categories(
|
||||
array(
|
||||
'hide_empty' => true,
|
||||
'exclude' => array( absint( get_option( 'default_category' ) ) ),
|
||||
'orderby' => 'name',
|
||||
'order' => 'ASC',
|
||||
)
|
||||
);
|
||||
|
||||
if ( empty( $categories ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$current_category_id = is_category() ? (int) get_queried_object_id() : 0;
|
||||
?>
|
||||
<nav class="news-category-nav" aria-label="<?php esc_attr_e( 'Categorias de notícias', 'gustavoo-portfolio' ); ?>">
|
||||
<div class="news-category-nav__inner site-shell">
|
||||
<a class="news-category-nav__link<?php echo is_home() ? ' is-current' : ''; ?>" href="<?php echo esc_url( gustavoo_portfolio_get_blog_url() ); ?>"><?php esc_html_e( 'Últimas notícias', 'gustavoo-portfolio' ); ?></a>
|
||||
<?php foreach ( $categories as $category ) : ?>
|
||||
<a class="news-category-nav__link<?php echo $current_category_id === (int) $category->term_id ? ' is-current' : ''; ?>" href="<?php echo esc_url( get_category_link( $category ) ); ?>"><?php echo esc_html( $category->name ); ?></a>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</nav>
|
||||
<?php
|
||||
}
|
||||
|
||||
/** Print editorial categories inside the mobile hamburger panel. */
|
||||
function gustavoo_portfolio_mobile_news_category_menu() {
|
||||
if ( has_nav_menu( 'news_categories' ) ) {
|
||||
?>
|
||||
<div class="mobile-news-categories">
|
||||
<p class="mobile-news-categories__title"><?php esc_html_e( 'Categorias', 'gustavoo-portfolio' ); ?></p>
|
||||
<?php
|
||||
wp_nav_menu(
|
||||
array(
|
||||
'theme_location' => 'news_categories',
|
||||
'menu_class' => 'mobile-news-categories__list',
|
||||
'container' => false,
|
||||
'fallback_cb' => false,
|
||||
'depth' => 1,
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
<?php
|
||||
return;
|
||||
}
|
||||
|
||||
$categories = get_categories(
|
||||
array(
|
||||
'hide_empty' => true,
|
||||
'exclude' => array( absint( get_option( 'default_category' ) ) ),
|
||||
'orderby' => 'name',
|
||||
'order' => 'ASC',
|
||||
)
|
||||
);
|
||||
|
||||
if ( empty( $categories ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$current_category_id = is_category() ? (int) get_queried_object_id() : 0;
|
||||
?>
|
||||
<div class="mobile-news-categories">
|
||||
<p class="mobile-news-categories__title"><?php esc_html_e( 'Categorias', 'gustavoo-portfolio' ); ?></p>
|
||||
<ul class="mobile-news-categories__list">
|
||||
<li><a class="<?php echo is_home() ? 'is-current' : ''; ?>" href="<?php echo esc_url( gustavoo_portfolio_get_blog_url() ); ?>"><?php esc_html_e( 'Últimas notícias', 'gustavoo-portfolio' ); ?></a></li>
|
||||
<?php foreach ( $categories as $category ) : ?>
|
||||
<li><a class="<?php echo $current_category_id === (int) $category->term_id ? 'is-current' : ''; ?>" href="<?php echo esc_url( get_category_link( $category ) ); ?>"><?php echo esc_html( $category->name ); ?></a></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve the image used by an editorial card.
|
||||
*
|
||||
* Seeded demo posts use a local theme image until an editor assigns a
|
||||
* featured image in WordPress.
|
||||
*
|
||||
* @param int $post_id Post ID.
|
||||
* @param string $size Registered image size.
|
||||
* @return string
|
||||
*/
|
||||
function gustavoo_portfolio_get_news_image_url( $post_id = 0, $size = 'gustavoo-post-card' ) {
|
||||
$post_id = $post_id ? absint( $post_id ) : get_the_ID();
|
||||
$image = get_the_post_thumbnail_url( $post_id, $size );
|
||||
|
||||
if ( $image ) {
|
||||
return $image;
|
||||
}
|
||||
|
||||
return (string) get_post_meta( $post_id, '_gso_news_image', true );
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessible fallback menu for a site that has not assigned a WordPress menu yet.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_primary_menu_fallback() {
|
||||
?>
|
||||
<ul id="primary-menu" class="primary-menu">
|
||||
<li class="menu-item"><a href="<?php echo esc_url( gustavoo_portfolio_section_url( 'sobre' ) ); ?>"><?php esc_html_e( 'Sobre', 'gustavoo-portfolio' ); ?></a></li>
|
||||
<li class="menu-item"><a href="<?php echo esc_url( gustavoo_portfolio_section_url( 'servicos' ) ); ?>"><?php esc_html_e( 'Serviços', 'gustavoo-portfolio' ); ?></a></li>
|
||||
<li class="menu-item"><a href="<?php echo esc_url( gustavoo_portfolio_section_url( 'projetos' ) ); ?>"><?php esc_html_e( 'Projetos', 'gustavoo-portfolio' ); ?></a></li>
|
||||
<li class="menu-item"><a href="<?php echo esc_url( gustavoo_portfolio_get_blog_url() ); ?>"><?php esc_html_e( 'Blog', 'gustavoo-portfolio' ); ?></a></li>
|
||||
<li class="menu-item"><a href="<?php echo esc_url( gustavoo_portfolio_section_url( 'contato' ) ); ?>"><?php esc_html_e( 'Contato', 'gustavoo-portfolio' ); ?></a></li>
|
||||
</ul>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Return supported social profile links.
|
||||
*
|
||||
* @return array<string, array{label:string,url:string}>
|
||||
*/
|
||||
function gustavoo_portfolio_get_social_links() {
|
||||
$profiles = array(
|
||||
'linkedin' => array(
|
||||
'label' => __( 'LinkedIn', 'gustavoo-portfolio' ),
|
||||
'url' => (string) gustavoo_portfolio_get_setting( 'linkedin_url' ),
|
||||
),
|
||||
'instagram' => array(
|
||||
'label' => __( 'Instagram', 'gustavoo-portfolio' ),
|
||||
'url' => (string) gustavoo_portfolio_get_setting( 'instagram_url' ),
|
||||
),
|
||||
);
|
||||
|
||||
return array_filter(
|
||||
$profiles,
|
||||
static function ( $profile ) {
|
||||
return ! empty( $profile['url'] );
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print social links with explicit new-window text for assistive technology.
|
||||
*
|
||||
* @param string $class Optional list class.
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_social_links( $class = 'social-links' ) {
|
||||
$profiles = gustavoo_portfolio_get_social_links();
|
||||
|
||||
if ( empty( $profiles ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
printf( '<ul class="%s">', esc_attr( $class ) );
|
||||
|
||||
foreach ( $profiles as $slug => $profile ) {
|
||||
printf(
|
||||
'<li class="social-links__item social-links__item--%1$s"><a href="%2$s" target="_blank" rel="noopener noreferrer external"><span>%3$s</span><span class="screen-reader-text"> %4$s</span></a></li>',
|
||||
esc_attr( $slug ),
|
||||
esc_url( $profile['url'] ),
|
||||
esc_html( $profile['label'] ),
|
||||
esc_html__( '(abre em uma nova guia)', 'gustavoo-portfolio' )
|
||||
);
|
||||
}
|
||||
|
||||
echo '</ul>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Print share links for a blog post using inline brand SVG icons.
|
||||
*
|
||||
* @param string $class Optional wrapper class.
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_post_share_links( $class = 'entry-share' ) {
|
||||
$share_url = rawurlencode( get_permalink() );
|
||||
$share_title = rawurlencode( get_the_title() );
|
||||
$links = array(
|
||||
'WhatsApp' => array(
|
||||
'url' => 'https://api.whatsapp.com/send?text=' . $share_title . '%20' . $share_url,
|
||||
'icon' => '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M20.5 3.5A11.8 11.8 0 0 0 12.1 0C5.6 0 .3 5.3.3 11.8c0 2.1.5 4.1 1.6 5.9L.2 23.8l6.3-1.7a11.8 11.8 0 0 0 5.6 1.4h.1c6.5 0 11.8-5.3 11.8-11.8 0-3.1-1.2-6-3.5-8.2Zm-8.4 17.9c-1.8 0-3.5-.5-5-1.4l-.4-.2-3.7 1 1-3.6-.2-.4a9.6 9.6 0 1 1 8.3 4.6Zm5.3-7.2c-.3-.2-1.7-.8-2-.9-.3-.1-.5-.2-.7.2-.2.3-.8.9-.9 1.1-.2.2-.3.2-.6.1-1.7-.8-2.8-1.5-3.9-3.4-.3-.5.3-.5.8-1.7.1-.2 0-.4 0-.6l-.9-2.1c-.2-.6-.5-.5-.7-.5h-.6c-.2 0-.5.1-.8.4-.3.3-1 1-1 2.4s1 2.8 1.1 3c.1.2 2 3.1 4.9 4.4 1.8.8 2.5.9 3.4.8.5-.1 1.7-.7 1.9-1.4.2-.7.2-1.3.1-1.4-.1-.2-.3-.3-.6-.4Z" fill="currentColor"/></svg>',
|
||||
),
|
||||
'Facebook' => array(
|
||||
'url' => 'https://www.facebook.com/sharer/sharer.php?u=' . $share_url,
|
||||
'icon' => '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M13.5 22v-8h2.7l.4-3h-3.1V9.1c0-.9.3-1.5 1.6-1.5h1.7V4.9c-.3 0-1.3-.1-2.5-.1-2.5 0-4.2 1.5-4.2 4.3V11H7.3v3h2.8v8h3.4Z" fill="currentColor"/></svg>',
|
||||
),
|
||||
'X' => array(
|
||||
'url' => 'https://twitter.com/intent/tweet?text=' . $share_title . '&url=' . $share_url,
|
||||
'icon' => '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M18.9 2h3.7l-8.1 9.3L24 22h-7.4l-5.8-7.6L4.2 22H.5l8.4-9.7L0 2h7.6l5.2 6.9L18.9 2Zm-1.3 17.9h2.1L6.4 4H4.1l13.5 15.9Z" fill="currentColor"/></svg>',
|
||||
),
|
||||
'LinkedIn' => array(
|
||||
'url' => 'https://www.linkedin.com/sharing/share-offsite/?url=' . $share_url,
|
||||
'icon' => '<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path d="M5.2 3.4A2.2 2.2 0 1 1 .8 3.4a2.2 2.2 0 0 1 4.4 0ZM1.1 7h4.2v13.5H1.1V7Zm6.8 0h4v1.8h.1c.6-1.1 2-2.2 4.1-2.2 4.4 0 5.2 2.9 5.2 6.7v7.2h-4.2v-6.4c0-1.5 0-3.5-2.1-3.5s-2.4 1.7-2.4 3.4v6.5H7.9V7Z" fill="currentColor"/></svg>',
|
||||
),
|
||||
);
|
||||
|
||||
printf( '<div class="%1$s" aria-label="%2$s">', esc_attr( $class ), esc_attr__( 'Compartilhar postagem', 'gustavoo-portfolio' ) );
|
||||
|
||||
foreach ( $links as $label => $link ) {
|
||||
printf(
|
||||
'<a href="%1$s" target="_blank" rel="noopener noreferrer" aria-label="%2$s">%3$s<span class="screen-reader-text">%2$s</span></a>',
|
||||
esc_url( $link['url'] ),
|
||||
esc_attr( $label ),
|
||||
$link['icon'] // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Static SVG markup.
|
||||
);
|
||||
}
|
||||
|
||||
echo '</div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a configured phone number to a WhatsApp URL.
|
||||
*
|
||||
* @param string $phone Raw phone number.
|
||||
* @param string $message Optional pre-filled conversation message.
|
||||
* @return string
|
||||
*/
|
||||
function gustavoo_portfolio_get_whatsapp_url( $phone, $message = '' ) {
|
||||
$digits = preg_replace( '/\D+/', '', (string) $phone );
|
||||
|
||||
if ( ! $digits ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if ( in_array( strlen( $digits ), array( 10, 11 ), true ) ) {
|
||||
$digits = '55' . $digits;
|
||||
}
|
||||
|
||||
$url = 'https://wa.me/' . $digits;
|
||||
$message = trim( wp_strip_all_tags( (string) $message ) );
|
||||
|
||||
if ( '' !== $message ) {
|
||||
$url .= '?text=' . rawurlencode( $message );
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/** Print the configured floating WhatsApp contact link. */
|
||||
function gustavoo_portfolio_the_whatsapp_float() {
|
||||
$phone = (string) gustavoo_portfolio_get_setting( 'whatsapp' );
|
||||
$message = (string) gustavoo_portfolio_get_setting( 'whatsapp_message' );
|
||||
$url = gustavoo_portfolio_get_whatsapp_url( $phone, $message );
|
||||
|
||||
if ( ! $url ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="whatsapp-float-wrap"<?php echo is_customize_preview() ? ' data-customize-partial-id="gustavoo_portfolio_whatsapp_shortcut"' : ''; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Static attribute. ?>>
|
||||
<a class="whatsapp-float" href="<?php echo esc_url( $url ); ?>" target="_blank" rel="noopener noreferrer external" aria-label="<?php esc_attr_e( 'Conversar pelo WhatsApp (abre em uma nova guia)', 'gustavoo-portfolio' ); ?>">
|
||||
<svg viewBox="0 0 24 24" aria-hidden="true" focusable="false"><path fill="currentColor" d="M20.5 3.5A11.8 11.8 0 0 0 12.1 0C5.6 0 .3 5.3.3 11.8c0 2.1.5 4.1 1.6 5.9L.2 23.8l6.3-1.7a11.8 11.8 0 0 0 5.6 1.4h.1c6.5 0 11.8-5.3 11.8-11.8 0-3.1-1.2-6-3.5-8.2ZM12.1 21.4c-1.8 0-3.5-.5-5-1.4l-.4-.2-3.7 1 1-3.6-.2-.4a9.6 9.6 0 1 1 8.3 4.6Zm5.3-7.2c-.3-.2-1.7-.8-2-.9-.3-.1-.5-.2-.7.2-.2.3-.8.9-.9 1.1-.2.2-.3.2-.6.1-1.7-.8-2.8-1.5-3.9-3.4-.3-.5.3-.5.8-1.7.1-.2 0-.4 0-.6l-.9-2.1c-.2-.6-.5-.5-.7-.5h-.6c-.2 0-.5.1-.8.4-.3.3-1 1-1 2.4s1 2.8 1.1 3c.1.2 2 3.1 4.9 4.4 1.8.8 2.5.9 3.4.8.5-.1 1.7-.7 1.9-1.4.2-.7.2-1.3.1-1.4-.1-.2-.3-.3-.6-.4Z"/></svg>
|
||||
</a>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate an external project URL without making a network request.
|
||||
*
|
||||
* @param string $url Candidate URL.
|
||||
* @return string Empty string when invalid.
|
||||
*/
|
||||
function gustavoo_portfolio_validate_project_url( $url ) {
|
||||
$url = esc_url_raw( (string) $url, array( 'http', 'https' ) );
|
||||
$scheme = wp_parse_url( $url, PHP_URL_SCHEME );
|
||||
$host = wp_parse_url( $url, PHP_URL_HOST );
|
||||
|
||||
if ( ! $url || ! $host || ! in_array( strtolower( (string) $scheme ), array( 'http', 'https' ), true ) ) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return $url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return featured projects first, then fill the requested limit by menu order.
|
||||
*
|
||||
* @param int $limit Maximum number of projects.
|
||||
* @return WP_Post[]
|
||||
*/
|
||||
function gustavoo_portfolio_get_home_projects( $limit = 6 ) {
|
||||
$limit = max( 1, min( 24, absint( $limit ) ) );
|
||||
|
||||
if ( ! post_type_exists( 'gso_project' ) ) {
|
||||
return array();
|
||||
}
|
||||
|
||||
$base_args = array(
|
||||
'post_type' => 'gso_project',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => $limit * 3,
|
||||
'orderby' => array(
|
||||
'menu_order' => 'ASC',
|
||||
'date' => 'DESC',
|
||||
),
|
||||
'ignore_sticky_posts' => true,
|
||||
'no_found_rows' => true,
|
||||
'update_post_term_cache' => true,
|
||||
);
|
||||
|
||||
$featured_args = $base_args;
|
||||
$featured_args['meta_query'] = array(
|
||||
array(
|
||||
'key' => '_gso_project_featured',
|
||||
'value' => array( '1', 'yes', 'on', 'true' ),
|
||||
'compare' => 'IN',
|
||||
),
|
||||
);
|
||||
|
||||
$featured = get_posts( $featured_args );
|
||||
$others = get_posts( $base_args );
|
||||
$projects = array();
|
||||
$seen = array();
|
||||
|
||||
foreach ( array_merge( $featured, $others ) as $project ) {
|
||||
if ( isset( $seen[ $project->ID ] ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$url = gustavoo_portfolio_validate_project_url( get_post_meta( $project->ID, '_gso_project_url', true ) );
|
||||
|
||||
if ( ! $url ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$seen[ $project->ID ] = true;
|
||||
$projects[] = $project;
|
||||
|
||||
if ( count( $projects ) >= $limit ) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return $projects;
|
||||
}
|
||||
|
||||
/**
|
||||
* Print post publication metadata.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_posted_on() {
|
||||
$published = sprintf(
|
||||
'<time class="entry-date published" datetime="%1$s">%2$s</time>',
|
||||
esc_attr( get_the_date( DATE_W3C ) ),
|
||||
esc_html( get_the_date() )
|
||||
);
|
||||
|
||||
printf(
|
||||
'<span class="posted-on"><span class="screen-reader-text">%1$s </span>%2$s</span>',
|
||||
esc_html__( 'Publicado em', 'gustavoo-portfolio' ),
|
||||
$published // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Escaped immediately above.
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print the post author link.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_posted_by() {
|
||||
printf(
|
||||
'<span class="byline"><span class="screen-reader-text">%1$s </span><a class="url fn n" href="%2$s">%3$s</a></span>',
|
||||
esc_html__( 'Por', 'gustavoo-portfolio' ),
|
||||
esc_url( get_author_posts_url( (int) get_the_author_meta( 'ID' ) ) ),
|
||||
esc_html( get_the_author() )
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Estimate reading time from the current post content.
|
||||
*
|
||||
* @param int|null $post_id Optional post ID.
|
||||
* @return string
|
||||
*/
|
||||
function gustavoo_portfolio_reading_time( $post_id = null ) {
|
||||
$post_id = $post_id ? absint( $post_id ) : get_the_ID();
|
||||
$content = wp_strip_all_tags( strip_shortcodes( (string) get_post_field( 'post_content', $post_id ) ) );
|
||||
$words = preg_split( '/\s+/u', trim( $content ), -1, PREG_SPLIT_NO_EMPTY );
|
||||
$minutes = max( 1, (int) ceil( count( is_array( $words ) ? $words : array() ) / 220 ) );
|
||||
|
||||
return sprintf(
|
||||
/* translators: %d: reading time in minutes. */
|
||||
_n( '%d min de leitura', '%d min de leitura', $minutes, 'gustavoo-portfolio' ),
|
||||
$minutes
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Print category and tag links for a post.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_entry_terms() {
|
||||
$categories = get_the_category_list( esc_html_x( ', ', 'category list separator', 'gustavoo-portfolio' ) );
|
||||
$tags = get_the_tag_list( '', esc_html_x( ', ', 'tag list separator', 'gustavoo-portfolio' ) );
|
||||
|
||||
if ( $categories ) {
|
||||
printf(
|
||||
'<div class="entry-terms entry-terms--categories"><span>%1$s</span> %2$s</div>',
|
||||
esc_html__( 'Categorias:', 'gustavoo-portfolio' ),
|
||||
wp_kses_post( $categories )
|
||||
);
|
||||
}
|
||||
|
||||
if ( $tags ) {
|
||||
printf(
|
||||
'<div class="entry-terms entry-terms--tags"><span>%1$s</span> %2$s</div>',
|
||||
esc_html__( 'Tags:', 'gustavoo-portfolio' ),
|
||||
wp_kses_post( $tags )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Print main-query pagination with accessible labels.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_pagination() {
|
||||
the_posts_pagination(
|
||||
array(
|
||||
'mid_size' => 1,
|
||||
'prev_text' => sprintf( '<span aria-hidden="true">←</span> %s', esc_html__( 'Anteriores', 'gustavoo-portfolio' ) ),
|
||||
'next_text' => sprintf( '%s <span aria-hidden="true">→</span>', esc_html__( 'Próximos', 'gustavoo-portfolio' ) ),
|
||||
'screen_reader_text' => __( 'Navegação entre páginas', 'gustavoo-portfolio' ),
|
||||
)
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
<?php
|
||||
/**
|
||||
* Widget areas and the reusable newsletter widget.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register sidebars used by blog and footer templates.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_register_sidebars() {
|
||||
$shared = array(
|
||||
'before_widget' => '<section id="%1$s" class="widget %2$s">',
|
||||
'after_widget' => '</section>',
|
||||
'before_title' => '<h2 class="widget__title">',
|
||||
'after_title' => '</h2>',
|
||||
);
|
||||
|
||||
register_sidebar(
|
||||
array_merge(
|
||||
$shared,
|
||||
array(
|
||||
'name' => __( 'Barra lateral do blog', 'gustavoo-portfolio' ),
|
||||
'id' => 'sidebar-blog',
|
||||
'description' => __( 'Widgets exibidos ao lado de posts, arquivos e buscas.', 'gustavoo-portfolio' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
register_sidebar(
|
||||
array_merge(
|
||||
$shared,
|
||||
array(
|
||||
'name' => __( 'Rodapé — coluna 1', 'gustavoo-portfolio' ),
|
||||
'id' => 'footer-1',
|
||||
'description' => __( 'Primeira coluna de widgets do rodapé.', 'gustavoo-portfolio' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
register_sidebar(
|
||||
array_merge(
|
||||
$shared,
|
||||
array(
|
||||
'name' => __( 'Rodapé — coluna 2', 'gustavoo-portfolio' ),
|
||||
'id' => 'footer-2',
|
||||
'description' => __( 'Segunda coluna de widgets do rodapé.', 'gustavoo-portfolio' ),
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
add_action( 'widgets_init', 'gustavoo_portfolio_register_sidebars' );
|
||||
|
||||
/**
|
||||
* Newsletter widget backed by the same safe Fluent Forms renderer as the CTA.
|
||||
*/
|
||||
class Gustavao_Portfolio_Newsletter_Widget extends WP_Widget {
|
||||
/**
|
||||
* Register the widget with WordPress.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct(
|
||||
'gustavoo_portfolio_newsletter',
|
||||
__( 'Gustavo — Newsletter', 'gustavoo-portfolio' ),
|
||||
array(
|
||||
'classname' => 'widget_newsletter',
|
||||
'description' => __( 'Exibe a chamada de newsletter integrada ao Fluent Forms e FluentCRM.', 'gustavoo-portfolio' ),
|
||||
'customize_selective_refresh' => true,
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Render widget front end.
|
||||
*
|
||||
* @param array<string, string> $args Sidebar wrappers.
|
||||
* @param array<string, mixed> $instance Saved instance.
|
||||
* @return void
|
||||
*/
|
||||
public function widget( $args, $instance ) {
|
||||
$title = ! empty( $instance['title'] ) ? $instance['title'] : gustavoo_portfolio_get_setting( 'newsletter_heading' );
|
||||
$text = ! empty( $instance['text'] ) ? $instance['text'] : gustavoo_portfolio_get_setting( 'newsletter_text' );
|
||||
$form_id = ! empty( $instance['form_id'] ) ? absint( $instance['form_id'] ) : absint( gustavoo_portfolio_get_setting( 'newsletter_form_id' ) );
|
||||
|
||||
echo $args['before_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Registered sidebar wrapper.
|
||||
|
||||
if ( $title ) {
|
||||
echo $args['before_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Registered sidebar wrapper.
|
||||
echo esc_html( $title );
|
||||
echo $args['after_title']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Registered sidebar wrapper.
|
||||
}
|
||||
|
||||
if ( $text ) {
|
||||
printf( '<p class="widget_newsletter__text">%s</p>', esc_html( $text ) );
|
||||
}
|
||||
|
||||
gustavoo_portfolio_the_fluent_form( $form_id, 'newsletter' );
|
||||
|
||||
echo $args['after_widget']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Registered sidebar wrapper.
|
||||
}
|
||||
|
||||
/**
|
||||
* Render widget controls.
|
||||
*
|
||||
* @param array<string, mixed> $instance Saved instance.
|
||||
* @return void
|
||||
*/
|
||||
public function form( $instance ) {
|
||||
$title = isset( $instance['title'] ) ? (string) $instance['title'] : '';
|
||||
$text = isset( $instance['text'] ) ? (string) $instance['text'] : '';
|
||||
$form_id = isset( $instance['form_id'] ) ? absint( $instance['form_id'] ) : 0;
|
||||
?>
|
||||
<p>
|
||||
<label for="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>"><?php esc_html_e( 'Título:', 'gustavoo-portfolio' ); ?></label>
|
||||
<input class="widefat" id="<?php echo esc_attr( $this->get_field_id( 'title' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'title' ) ); ?>" type="text" value="<?php echo esc_attr( $title ); ?>">
|
||||
</p>
|
||||
<p>
|
||||
<label for="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>"><?php esc_html_e( 'Texto:', 'gustavoo-portfolio' ); ?></label>
|
||||
<textarea class="widefat" rows="4" id="<?php echo esc_attr( $this->get_field_id( 'text' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'text' ) ); ?>"><?php echo esc_textarea( $text ); ?></textarea>
|
||||
</p>
|
||||
<p>
|
||||
<label for="<?php echo esc_attr( $this->get_field_id( 'form_id' ) ); ?>"><?php esc_html_e( 'ID do Fluent Forms (vazio usa o global):', 'gustavoo-portfolio' ); ?></label>
|
||||
<input class="tiny-text" id="<?php echo esc_attr( $this->get_field_id( 'form_id' ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( 'form_id' ) ); ?>" type="number" min="0" step="1" value="<?php echo esc_attr( $form_id ); ?>">
|
||||
</p>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitize widget settings.
|
||||
*
|
||||
* @param array<string, mixed> $new_instance New values.
|
||||
* @param array<string, mixed> $old_instance Previous values.
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
public function update( $new_instance, $old_instance ) {
|
||||
unset( $old_instance );
|
||||
|
||||
return array(
|
||||
'title' => isset( $new_instance['title'] ) ? sanitize_text_field( $new_instance['title'] ) : '',
|
||||
'text' => isset( $new_instance['text'] ) ? sanitize_textarea_field( $new_instance['text'] ) : '',
|
||||
'form_id' => isset( $new_instance['form_id'] ) ? absint( $new_instance['form_id'] ) : 0,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Register the newsletter widget after core has loaded WP_Widget.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_register_widgets() {
|
||||
register_widget( 'Gustavao_Portfolio_Newsletter_Widget' );
|
||||
}
|
||||
add_action( 'widgets_init', 'gustavoo_portfolio_register_widgets' );
|
||||
|
||||
/**
|
||||
* Add one newsletter widget to the blog sidebar on first theme activation.
|
||||
*
|
||||
* Existing widget arrangements are preserved and the operation is idempotent.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
function gustavoo_portfolio_seed_newsletter_widget() {
|
||||
$widget_id_base = 'gustavoo_portfolio_newsletter';
|
||||
$instances = get_option( 'widget_' . $widget_id_base, array() );
|
||||
$instances = is_array( $instances ) ? $instances : array();
|
||||
$sidebars = wp_get_sidebars_widgets();
|
||||
$sidebars = is_array( $sidebars ) ? $sidebars : array();
|
||||
|
||||
foreach ( $sidebars as $widgets ) {
|
||||
foreach ( (array) $widgets as $widget_id ) {
|
||||
if ( str_starts_with( (string) $widget_id, $widget_id_base . '-' ) ) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$indexes = array_filter( array_keys( $instances ), 'is_int' );
|
||||
$index = $indexes ? max( $indexes ) + 1 : 1;
|
||||
|
||||
$instances[ $index ] = array(
|
||||
'title' => __( 'Newsletter', 'gustavoo-portfolio' ),
|
||||
'text' => __( 'Receba novos artigos sobre desenvolvimento, infraestrutura e automação.', 'gustavoo-portfolio' ),
|
||||
'form_id' => 0,
|
||||
);
|
||||
$instances['_multiwidget'] = 1;
|
||||
|
||||
$sidebars['sidebar-blog'] = array_values(
|
||||
array_merge(
|
||||
array( $widget_id_base . '-' . $index ),
|
||||
isset( $sidebars['sidebar-blog'] ) ? (array) $sidebars['sidebar-blog'] : array()
|
||||
)
|
||||
);
|
||||
|
||||
update_option( 'widget_' . $widget_id_base, $instances, false );
|
||||
update_option( 'sidebars_widgets', $sidebars, false );
|
||||
}
|
||||
add_action( 'after_switch_theme', 'gustavoo_portfolio_seed_newsletter_widget' );
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Main fallback template.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<main id="primary" class="site-main content-index">
|
||||
<header class="page-hero">
|
||||
<div class="site-shell page-hero__inner">
|
||||
<p class="eyebrow"><?php esc_html_e( 'Conteúdo', 'gustavoo-portfolio' ); ?></p>
|
||||
<h1 class="page-hero__title"><?php esc_html_e( 'Publicações recentes', 'gustavoo-portfolio' ); ?></h1>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="site-shell article-layout">
|
||||
<div class="article-layout__main">
|
||||
<?php if ( have_posts() ) : ?>
|
||||
<div class="posts-grid">
|
||||
<?php
|
||||
while ( have_posts() ) {
|
||||
the_post();
|
||||
get_template_part( 'template-parts/global/post-card' );
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php gustavoo_portfolio_pagination(); ?>
|
||||
<?php else : ?>
|
||||
<?php get_template_part( 'template-parts/content/content', 'none' ); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php get_sidebar(); ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,27 @@
|
||||
<?php
|
||||
/**
|
||||
* Standard page template.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
get_header();
|
||||
?>
|
||||
|
||||
<main id="primary" class="site-main page-main">
|
||||
<div class="site-shell content-narrow">
|
||||
<?php
|
||||
while ( have_posts() ) {
|
||||
the_post();
|
||||
get_template_part( 'template-parts/content/content', 'page' );
|
||||
|
||||
if ( comments_open() || get_comments_number() ) {
|
||||
comments_template();
|
||||
}
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
|
After Width: | Height: | Size: 950 KiB |
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
/**
|
||||
* Search results.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
get_header();
|
||||
$gustavoo_search_query = get_search_query();
|
||||
?>
|
||||
|
||||
<main id="primary" class="site-main search-main">
|
||||
<header class="page-hero page-hero--search">
|
||||
<div class="site-shell page-hero__inner">
|
||||
<p class="eyebrow"><?php esc_html_e( 'Pesquisa', 'gustavoo-portfolio' ); ?></p>
|
||||
<h1 class="page-hero__title">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: search query. */
|
||||
esc_html__( 'Resultados para “%s”', 'gustavoo-portfolio' ),
|
||||
esc_html( $gustavoo_search_query )
|
||||
);
|
||||
?>
|
||||
</h1>
|
||||
<div class="page-hero__search"><?php get_search_form(); ?></div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="site-shell article-layout">
|
||||
<div class="article-layout__main">
|
||||
<?php if ( have_posts() ) : ?>
|
||||
<p class="results-count">
|
||||
<?php
|
||||
global $wp_query;
|
||||
printf(
|
||||
/* translators: %s: number of search results. */
|
||||
esc_html( _n( '%s resultado encontrado', '%s resultados encontrados', (int) $wp_query->found_posts, 'gustavoo-portfolio' ) ),
|
||||
esc_html( number_format_i18n( (int) $wp_query->found_posts ) )
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<div class="posts-grid">
|
||||
<?php
|
||||
while ( have_posts() ) {
|
||||
the_post();
|
||||
get_template_part( 'template-parts/global/post-card' );
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<?php gustavoo_portfolio_pagination(); ?>
|
||||
<?php else : ?>
|
||||
<?php get_template_part( 'template-parts/content/content', 'none' ); ?>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
<?php get_sidebar(); ?>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<?php
|
||||
get_footer();
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
/**
|
||||
* Accessible search form.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$gustavoo_search_id = wp_unique_id( 'site-search-' );
|
||||
?>
|
||||
<form role="search" method="get" class="search-form" action="<?php echo esc_url( home_url( '/' ) ); ?>">
|
||||
<label class="search-form__label" for="<?php echo esc_attr( $gustavoo_search_id ); ?>">
|
||||
<span class="screen-reader-text"><?php echo esc_html_x( 'Pesquisar por:', 'label', 'gustavoo-portfolio' ); ?></span>
|
||||
<input id="<?php echo esc_attr( $gustavoo_search_id ); ?>" type="search" class="search-form__field" placeholder="<?php echo esc_attr_x( 'Pesquisar no blog…', 'placeholder', 'gustavoo-portfolio' ); ?>" value="<?php echo esc_attr( get_search_query() ); ?>" name="s">
|
||||
</label>
|
||||
<button type="submit" class="search-form__submit">
|
||||
<span><?php echo esc_html_x( 'Pesquisar', 'submit button', 'gustavoo-portfolio' ); ?></span>
|
||||
<span aria-hidden="true">→</span>
|
||||
</button>
|
||||
</form>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* Blog sidebar.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<aside id="secondary" class="sidebar" aria-label="<?php esc_attr_e( 'Barra lateral do blog', 'gustavoo-portfolio' ); ?>">
|
||||
<?php if ( is_active_sidebar( 'sidebar-blog' ) ) : ?>
|
||||
<?php dynamic_sidebar( 'sidebar-blog' ); ?>
|
||||
<?php else : ?>
|
||||
<section class="widget widget_search">
|
||||
<h2 class="widget__title"><?php esc_html_e( 'Pesquisar', 'gustavoo-portfolio' ); ?></h2>
|
||||
<?php get_search_form(); ?>
|
||||
</section>
|
||||
|
||||
<section class="widget widget_categories">
|
||||
<h2 class="widget__title"><?php esc_html_e( 'Categorias', 'gustavoo-portfolio' ); ?></h2>
|
||||
<ul>
|
||||
<?php
|
||||
wp_list_categories(
|
||||
array(
|
||||
'title_li' => '',
|
||||
'show_count' => true,
|
||||
)
|
||||
);
|
||||
?>
|
||||
</ul>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
</aside>
|
||||
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
/**
|
||||
* Single blog post template.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
get_header();
|
||||
|
||||
while ( have_posts() ) :
|
||||
the_post();
|
||||
?>
|
||||
<main id="primary" class="site-main single-post-main">
|
||||
<header class="entry-hero">
|
||||
<div class="site-shell entry-hero__inner">
|
||||
<nav class="entry-breadcrumbs" aria-label="<?php esc_attr_e( 'Navegação estrutural', 'gustavoo-portfolio' ); ?>">
|
||||
<a href="<?php echo esc_url( home_url( '/' ) ); ?>"><?php esc_html_e( 'Início', 'gustavoo-portfolio' ); ?></a>
|
||||
<span aria-hidden="true">›</span>
|
||||
<a href="<?php echo esc_url( gustavoo_portfolio_get_blog_url() ); ?>"><?php esc_html_e( 'Últimas notícias', 'gustavoo-portfolio' ); ?></a>
|
||||
<?php $gustavoo_breadcrumb_categories = get_the_category(); ?>
|
||||
<?php if ( ! empty( $gustavoo_breadcrumb_categories ) ) : ?>
|
||||
<span aria-hidden="true">›</span>
|
||||
<a href="<?php echo esc_url( get_category_link( $gustavoo_breadcrumb_categories[0] ) ); ?>"><?php echo esc_html( $gustavoo_breadcrumb_categories[0]->name ); ?></a>
|
||||
<?php endif; ?>
|
||||
</nav>
|
||||
<?php $gustavoo_categories = get_the_category(); ?>
|
||||
<?php if ( ! empty( $gustavoo_categories ) ) : ?>
|
||||
<a class="entry-category-badge" href="<?php echo esc_url( get_category_link( $gustavoo_categories[0] ) ); ?>"><?php echo esc_html( $gustavoo_categories[0]->name ); ?></a>
|
||||
<?php endif; ?>
|
||||
<?php the_title( '<h1 class="entry-hero__title">', '</h1>' ); ?>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="site-shell entry-post-meta">
|
||||
<div class="entry-post-meta__author">
|
||||
<strong><?php echo esc_html( get_the_author() ); ?></strong>
|
||||
<span aria-hidden="true">·</span>
|
||||
<span><?php esc_html_e( 'Publicado em', 'gustavoo-portfolio' ); ?> <?php echo esc_html( get_the_date() ); ?></span>
|
||||
<span aria-hidden="true">·</span>
|
||||
<span><?php echo esc_html( gustavoo_portfolio_reading_time() ); ?></span>
|
||||
</div>
|
||||
<?php gustavoo_portfolio_post_share_links(); ?>
|
||||
</div>
|
||||
|
||||
<?php if ( has_post_thumbnail() ) : ?>
|
||||
<figure class="entry-featured-image">
|
||||
<?php the_post_thumbnail( 'full', array( 'class' => 'entry-featured-image__image' ) ); ?>
|
||||
</figure>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="site-shell article-layout article-layout--single">
|
||||
<article id="post-<?php the_ID(); ?>" <?php post_class( 'article article--single' ); ?>>
|
||||
<div class="entry-content prose">
|
||||
<?php the_content(); ?>
|
||||
<?php
|
||||
wp_link_pages(
|
||||
array(
|
||||
'before' => '<nav class="page-links" aria-label="' . esc_attr__( 'Páginas deste artigo', 'gustavoo-portfolio' ) . '"><span>' . esc_html__( 'Páginas:', 'gustavoo-portfolio' ) . '</span>',
|
||||
'after' => '</nav>',
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
|
||||
<footer class="entry-footer">
|
||||
<?php gustavoo_portfolio_entry_terms(); ?>
|
||||
</footer>
|
||||
|
||||
<?php
|
||||
$gustavoo_categories = get_the_category();
|
||||
?>
|
||||
|
||||
<section class="post-share-panel" aria-labelledby="post-share-title">
|
||||
<h2 id="post-share-title" class="post-share-panel__title"><?php esc_html_e( 'Compartilhar:', 'gustavoo-portfolio' ); ?></h2>
|
||||
<?php gustavoo_portfolio_post_share_links( 'post-share-panel__links' ); ?>
|
||||
</section>
|
||||
|
||||
<?php if ( ! empty( $gustavoo_categories ) ) : ?>
|
||||
<?php
|
||||
$gustavoo_related_posts = new WP_Query(
|
||||
array(
|
||||
'category__in' => wp_list_pluck( $gustavoo_categories, 'term_id' ),
|
||||
'post__not_in' => array( get_the_ID() ),
|
||||
'posts_per_page' => 3,
|
||||
'ignore_sticky_posts' => true,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
)
|
||||
);
|
||||
?>
|
||||
<?php if ( $gustavoo_related_posts->have_posts() ) : ?>
|
||||
<section class="related-posts" aria-labelledby="related-posts-title">
|
||||
<div class="related-posts__heading"><span></span><h2 id="related-posts-title"><?php esc_html_e( 'Relacionadas', 'gustavoo-portfolio' ); ?></h2><span></span></div>
|
||||
<div class="related-posts__grid">
|
||||
<?php while ( $gustavoo_related_posts->have_posts() ) : $gustavoo_related_posts->the_post(); ?>
|
||||
<article <?php post_class( 'related-post' ); ?>>
|
||||
<a class="related-post__link" href="<?php the_permalink(); ?>">
|
||||
<?php if ( has_post_thumbnail() ) : ?>
|
||||
<?php the_post_thumbnail( 'gustavoo-post-card', array( 'class' => 'related-post__image', 'loading' => 'lazy', 'decoding' => 'async' ) ); ?>
|
||||
<?php endif; ?>
|
||||
<h3 class="related-post__title"><?php the_title(); ?></h3>
|
||||
</a>
|
||||
</article>
|
||||
<?php endwhile; ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php endif; ?>
|
||||
<?php wp_reset_postdata(); ?>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php $gustavoo_previous_post = get_previous_post(); ?>
|
||||
<?php $gustavoo_next_post = get_next_post(); ?>
|
||||
<?php if ( $gustavoo_previous_post || $gustavoo_next_post ) : ?>
|
||||
<nav class="post-navigation post-navigation--editorial" aria-label="<?php esc_attr_e( 'Navegação entre artigos', 'gustavoo-portfolio' ); ?>">
|
||||
<div class="nav-links">
|
||||
<?php if ( $gustavoo_previous_post ) : ?>
|
||||
<a class="nav-previous" href="<?php echo esc_url( get_permalink( $gustavoo_previous_post ) ); ?>"><span class="nav-subtitle">← <?php esc_html_e( 'Anterior', 'gustavoo-portfolio' ); ?></span><span class="nav-title"><?php echo esc_html( get_the_title( $gustavoo_previous_post ) ); ?></span></a>
|
||||
<?php endif; ?>
|
||||
<?php if ( $gustavoo_next_post ) : ?>
|
||||
<a class="nav-next" href="<?php echo esc_url( get_permalink( $gustavoo_next_post ) ); ?>"><span class="nav-subtitle"><?php esc_html_e( 'Próximo', 'gustavoo-portfolio' ); ?> →</span><span class="nav-title"><?php echo esc_html( get_the_title( $gustavoo_next_post ) ); ?></span></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</nav>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( comments_open() || get_comments_number() ) {
|
||||
comments_template();
|
||||
}
|
||||
?>
|
||||
</article>
|
||||
|
||||
<?php get_sidebar(); ?>
|
||||
</div>
|
||||
</main>
|
||||
<?php
|
||||
endwhile;
|
||||
|
||||
get_footer();
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
Theme Name: Gustavo Portfolio
|
||||
Theme URI: https://gustavoo.me/
|
||||
Author: Gustavo Oliveira
|
||||
Author URI: https://gustavoo.me/
|
||||
Description: Tema clássico para o portfólio e blog de Gustavo Oliveira.
|
||||
Version: 1.1.0
|
||||
Requires at least: 6.5
|
||||
Requires PHP: 8.1
|
||||
Text Domain: gustavoo-portfolio
|
||||
License: GNU General Public License v2 or later
|
||||
License URI: https://www.gnu.org/licenses/gpl-2.0.html
|
||||
*/
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
/**
|
||||
* Empty result state.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
?>
|
||||
|
||||
<section class="no-results not-found" aria-labelledby="no-results-title">
|
||||
<h2 id="no-results-title" class="no-results__title"><?php esc_html_e( 'Nada encontrado', 'gustavoo-portfolio' ); ?></h2>
|
||||
<?php if ( is_search() ) : ?>
|
||||
<p><?php esc_html_e( 'Não encontramos conteúdo com esses termos. Tente palavras diferentes.', 'gustavoo-portfolio' ); ?></p>
|
||||
<?php get_search_form(); ?>
|
||||
<?php else : ?>
|
||||
<p><?php esc_html_e( 'Ainda não há publicações aqui.', 'gustavoo-portfolio' ); ?></p>
|
||||
<?php endif; ?>
|
||||
</section>
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/**
|
||||
* Page content.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
?>
|
||||
|
||||
<article id="post-<?php the_ID(); ?>" <?php post_class( 'page-article' ); ?>>
|
||||
<header class="page-article__header">
|
||||
<p class="eyebrow"><?php esc_html_e( 'Página', 'gustavoo-portfolio' ); ?></p>
|
||||
<?php the_title( '<h1 class="page-article__title">', '</h1>' ); ?>
|
||||
</header>
|
||||
|
||||
<?php if ( has_post_thumbnail() ) : ?>
|
||||
<figure class="page-article__media">
|
||||
<?php the_post_thumbnail( 'full', array( 'class' => 'page-article__image' ) ); ?>
|
||||
</figure>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="entry-content prose">
|
||||
<?php the_content(); ?>
|
||||
<?php
|
||||
wp_link_pages(
|
||||
array(
|
||||
'before' => '<nav class="page-links" aria-label="' . esc_attr__( 'Páginas deste conteúdo', 'gustavoo-portfolio' ) . '"><span>' . esc_html__( 'Páginas:', 'gustavoo-portfolio' ) . '</span>',
|
||||
'after' => '</nav>',
|
||||
)
|
||||
);
|
||||
?>
|
||||
</div>
|
||||
</article>
|
||||
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
/**
|
||||
* Front-page about section.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
$gustavoo_about_text = (string) gustavoo_portfolio_get_setting( 'about_text' );
|
||||
$gustavoo_about_secondary_text = (string) gustavoo_portfolio_get_setting( 'about_secondary_text' );
|
||||
?>
|
||||
|
||||
<section id="sobre" class="section section--about" aria-labelledby="about-title">
|
||||
<div class="site-shell about-layout">
|
||||
<header class="section__header about-layout__header">
|
||||
<p class="eyebrow"><?php echo esc_html( gustavoo_portfolio_get_setting( 'about_eyebrow' ) ); ?></p>
|
||||
<h2 id="about-title" class="section__title"><?php echo esc_html( gustavoo_portfolio_get_setting( 'about_title' ) ); ?></h2>
|
||||
</header>
|
||||
|
||||
<div class="about-layout__content">
|
||||
<div class="prose prose--lead">
|
||||
<?php echo wp_kses_post( wpautop( esc_html( $gustavoo_about_text ) ) ); ?>
|
||||
<?php echo wp_kses_post( wpautop( esc_html( $gustavoo_about_secondary_text ) ) ); ?>
|
||||
</div>
|
||||
|
||||
<dl class="about-facts" aria-label="<?php esc_attr_e( 'Diferenciais profissionais', 'gustavoo-portfolio' ); ?>">
|
||||
<div class="about-fact">
|
||||
<dt><?php esc_html_e( 'Escopo', 'gustavoo-portfolio' ); ?></dt>
|
||||
<dd><?php esc_html_e( 'Da regra de negócio à infraestrutura', 'gustavoo-portfolio' ); ?></dd>
|
||||
</div>
|
||||
<div class="about-fact">
|
||||
<dt><?php esc_html_e( 'Entrega', 'gustavoo-portfolio' ); ?></dt>
|
||||
<dd><?php esc_html_e( 'Código limpo, documentado e sustentável', 'gustavoo-portfolio' ); ?></dd>
|
||||
</div>
|
||||
<div class="about-fact">
|
||||
<dt><?php esc_html_e( 'Visão', 'gustavoo-portfolio' ); ?></dt>
|
||||
<dd><?php esc_html_e( 'Tecnologia alinhada ao crescimento', 'gustavoo-portfolio' ); ?></dd>
|
||||
</div>
|
||||
</dl>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
/**
|
||||
* Front-page contact section.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
$gustavoo_contact_form_id = absint( gustavoo_portfolio_get_setting( 'contact_form_id' ) );
|
||||
$gustavoo_email = sanitize_email( (string) gustavoo_portfolio_get_setting( 'email' ) );
|
||||
$gustavoo_privacy_url = get_privacy_policy_url();
|
||||
?>
|
||||
|
||||
<section id="contato" class="section section--contact" aria-labelledby="contact-title">
|
||||
<div class="site-shell contact-panel">
|
||||
<div class="contact-panel__content">
|
||||
<p class="eyebrow"><?php echo esc_html( gustavoo_portfolio_get_setting( 'contact_eyebrow' ) ); ?></p>
|
||||
<h2 id="contact-title" class="section__title"><?php echo esc_html( gustavoo_portfolio_get_setting( 'contact_heading' ) ); ?></h2>
|
||||
<p class="contact-panel__description"><?php echo esc_html( gustavoo_portfolio_get_setting( 'contact_text' ) ); ?></p>
|
||||
|
||||
<?php if ( $gustavoo_email ) : ?>
|
||||
<ul class="contact-list">
|
||||
<?php if ( $gustavoo_email ) : ?>
|
||||
<li><span><?php esc_html_e( 'E-mail', 'gustavoo-portfolio' ); ?></span><a href="<?php echo esc_url( 'mailto:' . $gustavoo_email ); ?>"><?php echo esc_html( antispambot( $gustavoo_email ) ); ?></a></li>
|
||||
<?php endif; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php gustavoo_portfolio_social_links( 'social-links social-links--contact' ); ?>
|
||||
</div>
|
||||
|
||||
<div class="contact-panel__form">
|
||||
<?php gustavoo_portfolio_the_fluent_form( $gustavoo_contact_form_id, 'contact' ); ?>
|
||||
<?php if ( $gustavoo_privacy_url ) : ?>
|
||||
<p class="form-privacy">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: privacy policy URL. */
|
||||
wp_kses_post( __( 'Ao enviar, você concorda com o tratamento dos dados conforme a <a href="%s">Política de Privacidade</a>.', 'gustavoo-portfolio' ) ),
|
||||
esc_url( $gustavoo_privacy_url )
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/**
|
||||
* Front-page hero.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
$gustavoo_hero_eyebrow = (string) gustavoo_portfolio_get_setting( 'hero_eyebrow' );
|
||||
$gustavoo_hero_title = (string) gustavoo_portfolio_get_setting( 'hero_title' );
|
||||
$gustavoo_hero_description = (string) gustavoo_portfolio_get_setting( 'hero_description' );
|
||||
$gustavoo_hero_primary_label = (string) gustavoo_portfolio_get_setting( 'hero_primary_label' );
|
||||
$gustavoo_hero_primary_url = (string) gustavoo_portfolio_get_setting( 'hero_primary_url' );
|
||||
$gustavoo_hero_secondary_label = (string) gustavoo_portfolio_get_setting( 'hero_secondary_label' );
|
||||
$gustavoo_hero_secondary_url = (string) gustavoo_portfolio_get_setting( 'hero_secondary_url' );
|
||||
$gustavoo_hero_sources = gustavoo_portfolio_get_picture_sources( 'hero-art' );
|
||||
?>
|
||||
|
||||
<section class="hero-stage" aria-labelledby="hero-title">
|
||||
<div class="site-shell hero">
|
||||
<div class="hero__content">
|
||||
<?php if ( $gustavoo_hero_eyebrow ) : ?>
|
||||
<p class="eyebrow hero__eyebrow"><?php echo esc_html( $gustavoo_hero_eyebrow ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<h1 id="hero-title" class="hero__title"><?php echo esc_html( $gustavoo_hero_title ); ?></h1>
|
||||
<p class="hero__description"><?php echo esc_html( $gustavoo_hero_description ); ?></p>
|
||||
|
||||
<div class="hero__actions">
|
||||
<?php if ( $gustavoo_hero_primary_label && $gustavoo_hero_primary_url ) : ?>
|
||||
<a class="button button--primary" href="<?php echo esc_url( $gustavoo_hero_primary_url ); ?>">
|
||||
<?php echo esc_html( $gustavoo_hero_primary_label ); ?> <span aria-hidden="true">→</span>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( $gustavoo_hero_secondary_label && $gustavoo_hero_secondary_url ) : ?>
|
||||
<a class="button button--secondary" href="<?php echo esc_url( $gustavoo_hero_secondary_url ); ?>">
|
||||
<?php echo esc_html( $gustavoo_hero_secondary_label ); ?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="hero__visual" aria-hidden="true">
|
||||
<div class="hero__visual-glow"></div>
|
||||
<picture>
|
||||
<?php if ( $gustavoo_hero_sources['webp'] ) : ?>
|
||||
<source srcset="<?php echo esc_url( $gustavoo_hero_sources['webp'] ); ?>" type="image/webp">
|
||||
<?php endif; ?>
|
||||
<img class="hero__image" src="<?php echo esc_url( $gustavoo_hero_sources['fallback'] ); ?>" width="1234" height="1280" alt="" loading="eager" decoding="async" fetchpriority="high">
|
||||
</picture>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Front-page latest posts.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
$gustavoo_blog_limit = max( 1, min( 12, absint( gustavoo_portfolio_get_setting( 'blog_limit', 4 ) ) ) );
|
||||
$gustavoo_posts = new WP_Query(
|
||||
array(
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => $gustavoo_blog_limit,
|
||||
'ignore_sticky_posts' => true,
|
||||
'no_found_rows' => true,
|
||||
)
|
||||
);
|
||||
?>
|
||||
|
||||
<section id="blog" class="section section--posts" aria-labelledby="latest-posts-title">
|
||||
<div class="site-shell">
|
||||
<header class="section__header section__header--split">
|
||||
<div>
|
||||
<p class="eyebrow"><?php echo esc_html( gustavoo_portfolio_get_setting( 'blog_eyebrow' ) ); ?></p>
|
||||
<h2 id="latest-posts-title" class="section__title"><?php echo esc_html( gustavoo_portfolio_get_setting( 'blog_title' ) ); ?></h2>
|
||||
</div>
|
||||
<p class="section__description"><?php echo esc_html( gustavoo_portfolio_get_setting( 'blog_text' ) ); ?></p>
|
||||
</header>
|
||||
|
||||
<?php if ( $gustavoo_posts->have_posts() ) : ?>
|
||||
<div class="posts-grid posts-grid--featured">
|
||||
<?php
|
||||
while ( $gustavoo_posts->have_posts() ) {
|
||||
$gustavoo_posts->the_post();
|
||||
get_template_part( 'template-parts/global/post-card' );
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
|
||||
<p class="section__action"><a class="button button--secondary" href="<?php echo esc_url( gustavoo_portfolio_get_blog_url() ); ?>"><?php esc_html_e( 'Explorar todos os artigos', 'gustavoo-portfolio' ); ?> <span aria-hidden="true">→</span></a></p>
|
||||
<?php else : ?>
|
||||
<div class="section__empty"><p><?php esc_html_e( 'O primeiro artigo está a caminho.', 'gustavoo-portfolio' ); ?></p></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php wp_reset_postdata(); ?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* Front-page project grid.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
$gustavoo_project_limit = max( 1, min( 24, absint( gustavoo_portfolio_get_setting( 'projects_limit', 6 ) ) ) );
|
||||
$gustavoo_projects = gustavoo_portfolio_get_home_projects( $gustavoo_project_limit );
|
||||
$gustavoo_archive_url = esc_url_raw( (string) gustavoo_portfolio_get_setting( 'projects_archive_url' ) );
|
||||
?>
|
||||
|
||||
<section id="projetos" class="section section--projects" aria-labelledby="projects-title">
|
||||
<div class="site-shell">
|
||||
<header class="section__header section__header--split">
|
||||
<div>
|
||||
<p class="eyebrow"><?php echo esc_html( gustavoo_portfolio_get_setting( 'projects_eyebrow' ) ); ?></p>
|
||||
<h2 id="projects-title" class="section__title"><?php echo esc_html( gustavoo_portfolio_get_setting( 'projects_title' ) ); ?></h2>
|
||||
</div>
|
||||
<p class="section__description"><?php echo esc_html( gustavoo_portfolio_get_setting( 'projects_text' ) ); ?></p>
|
||||
</header>
|
||||
|
||||
<?php if ( $gustavoo_projects ) : ?>
|
||||
<div class="projects-grid">
|
||||
<?php
|
||||
global $post;
|
||||
|
||||
foreach ( $gustavoo_projects as $post ) {
|
||||
setup_postdata( $post );
|
||||
get_template_part( 'template-parts/global/project-card' );
|
||||
}
|
||||
|
||||
wp_reset_postdata();
|
||||
?>
|
||||
</div>
|
||||
<?php else : ?>
|
||||
<div class="section__empty">
|
||||
<p><?php esc_html_e( 'Novos projetos serão publicados aqui em breve.', 'gustavoo-portfolio' ); ?></p>
|
||||
<?php if ( current_user_can( 'edit_posts' ) && post_type_exists( 'gso_project' ) ) : ?>
|
||||
<a class="text-link" href="<?php echo esc_url( admin_url( 'post-new.php?post_type=gso_project' ) ); ?>"><?php esc_html_e( 'Adicionar o primeiro projeto', 'gustavoo-portfolio' ); ?> <span aria-hidden="true">→</span></a>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( $gustavoo_archive_url ) : ?>
|
||||
<p class="section__action"><a class="button button--secondary" href="<?php echo esc_url( $gustavoo_archive_url ); ?>"><?php esc_html_e( 'Ver todos os projetos', 'gustavoo-portfolio' ); ?> <span aria-hidden="true">→</span></a></p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?php
|
||||
/**
|
||||
* Front-page services section.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
$gustavoo_services = gustavoo_portfolio_get_services();
|
||||
?>
|
||||
|
||||
<section id="servicos" class="section section--services" aria-labelledby="services-title">
|
||||
<div class="site-shell">
|
||||
<header class="section__header section__header--split">
|
||||
<div>
|
||||
<p class="eyebrow"><?php echo esc_html( gustavoo_portfolio_get_setting( 'services_eyebrow' ) ); ?></p>
|
||||
<h2 id="services-title" class="section__title"><?php echo esc_html( gustavoo_portfolio_get_setting( 'services_title' ) ); ?></h2>
|
||||
</div>
|
||||
<p class="section__description"><?php echo esc_html( gustavoo_portfolio_get_setting( 'services_description' ) ); ?></p>
|
||||
</header>
|
||||
|
||||
<div class="services-grid">
|
||||
<?php foreach ( $gustavoo_services as $gustavoo_service ) : ?>
|
||||
<article class="service-card">
|
||||
<p class="service-card__number" aria-hidden="true"><?php echo esc_html( $gustavoo_service['number'] ?? '' ); ?></p>
|
||||
<h3 class="service-card__title"><?php echo esc_html( $gustavoo_service['title'] ?? '' ); ?></h3>
|
||||
<p class="service-card__description"><?php echo esc_html( $gustavoo_service['description'] ?? '' ); ?></p>
|
||||
</article>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/** Compact editorial news card. @package Gustavo_Portfolio */
|
||||
|
||||
$gustavoo_args = isset( $args ) && is_array( $args ) ? $args : array();
|
||||
$gustavoo_is_featured = ! empty( $gustavoo_args['featured'] );
|
||||
$gustavoo_categories = get_the_category();
|
||||
$gustavoo_category = $gustavoo_categories ? $gustavoo_categories[0] : null;
|
||||
$gustavoo_image_url = gustavoo_portfolio_get_news_image_url( get_the_ID(), $gustavoo_is_featured ? 'large' : 'gustavoo-post-card' );
|
||||
?>
|
||||
<article <?php post_class( 'latest-news-card' . ( $gustavoo_is_featured ? ' latest-news-card--featured' : '' ) ); ?>>
|
||||
<a class="latest-news-card__media" href="<?php the_permalink(); ?>" aria-hidden="true" tabindex="-1">
|
||||
<?php if ( $gustavoo_image_url ) : ?>
|
||||
<img class="latest-news-card__image" src="<?php echo esc_url( $gustavoo_image_url ); ?>" loading="<?php echo $gustavoo_is_featured ? 'eager' : 'lazy'; ?>" decoding="async" alt="">
|
||||
<?php else : ?><span class="latest-news-card__placeholder" aria-hidden="true"></span><?php endif; ?>
|
||||
</a>
|
||||
<div class="latest-news-card__body">
|
||||
<?php if ( $gustavoo_category ) : ?><a class="latest-news-card__category" href="<?php echo esc_url( get_category_link( $gustavoo_category ) ); ?>"><?php echo esc_html( $gustavoo_category->name ); ?></a><?php endif; ?>
|
||||
<h2 class="latest-news-card__title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
|
||||
<time class="latest-news-card__date" datetime="<?php echo esc_attr( get_the_date( DATE_W3C ) ); ?>"><?php echo esc_html( get_the_date() ); ?></time>
|
||||
<?php if ( $gustavoo_is_featured && has_excerpt() ) : ?><p class="latest-news-card__excerpt"><?php echo esc_html( wp_trim_words( get_the_excerpt(), 28 ) ); ?></p><?php endif; ?>
|
||||
</div>
|
||||
</article>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php
|
||||
/**
|
||||
* Secondary compact news list for news and category pages.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
$gustavoo_args = isset( $args ) && is_array( $args ) ? $args : array();
|
||||
$gustavoo_query_args = array(
|
||||
'post_type' => 'post',
|
||||
'post_status' => 'publish',
|
||||
'posts_per_page' => 4,
|
||||
'post__not_in' => array_map( 'absint', $gustavoo_args['exclude'] ?? array() ),
|
||||
'ignore_sticky_posts' => true,
|
||||
'orderby' => 'date',
|
||||
'order' => 'DESC',
|
||||
);
|
||||
|
||||
if ( ! empty( $gustavoo_args['category_id'] ) ) {
|
||||
$gustavoo_query_args['cat'] = absint( $gustavoo_args['category_id'] );
|
||||
}
|
||||
|
||||
$gustavoo_latest_posts = new WP_Query( $gustavoo_query_args );
|
||||
|
||||
if ( ! $gustavoo_latest_posts->have_posts() ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<section class="latest-news-list" aria-labelledby="latest-news-list-title">
|
||||
<h2 id="latest-news-list-title" class="latest-news-list__heading"><?php esc_html_e( 'Últimas notícias', 'gustavoo-portfolio' ); ?></h2>
|
||||
<div class="latest-news-list__items">
|
||||
<?php while ( $gustavoo_latest_posts->have_posts() ) : $gustavoo_latest_posts->the_post(); ?>
|
||||
<?php $gustavoo_categories = get_the_category(); $gustavoo_category = $gustavoo_categories ? $gustavoo_categories[0] : null; $gustavoo_image_url = gustavoo_portfolio_get_news_image_url(); ?>
|
||||
<article <?php post_class( 'latest-news-list__item' ); ?>>
|
||||
<a class="latest-news-list__image" href="<?php the_permalink(); ?>" aria-hidden="true" tabindex="-1">
|
||||
<?php if ( $gustavoo_image_url ) : ?><img src="<?php echo esc_url( $gustavoo_image_url ); ?>" loading="lazy" decoding="async" alt=""><?php endif; ?>
|
||||
</a>
|
||||
<div class="latest-news-list__body">
|
||||
<?php if ( $gustavoo_category ) : ?><a class="latest-news-card__category" href="<?php echo esc_url( get_category_link( $gustavoo_category ) ); ?>"><?php echo esc_html( $gustavoo_category->name ); ?></a><?php endif; ?>
|
||||
<h3><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h3>
|
||||
<time datetime="<?php echo esc_attr( get_the_date( DATE_W3C ) ); ?>"><?php echo esc_html( get_the_date( 'D, d/m/Y · H:i' ) ); ?></time>
|
||||
</div>
|
||||
</article>
|
||||
<?php endwhile; ?>
|
||||
</div>
|
||||
</section>
|
||||
<?php wp_reset_postdata(); ?>
|
||||
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
/**
|
||||
* Global newsletter call to action, rendered before every site footer.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
$gustavoo_newsletter_form_id = absint( gustavoo_portfolio_get_setting( 'newsletter_form_id' ) );
|
||||
$gustavoo_privacy_url = get_privacy_policy_url();
|
||||
?>
|
||||
|
||||
<section class="section section--newsletter" aria-labelledby="newsletter-title">
|
||||
<div class="site-shell newsletter-panel">
|
||||
<div class="newsletter-panel__content">
|
||||
<p class="eyebrow"><?php echo esc_html( gustavoo_portfolio_get_setting( 'newsletter_eyebrow' ) ); ?></p>
|
||||
<h2 id="newsletter-title" class="newsletter-panel__title"><?php echo esc_html( gustavoo_portfolio_get_setting( 'newsletter_heading' ) ); ?></h2>
|
||||
<p class="newsletter-panel__description"><?php echo esc_html( gustavoo_portfolio_get_setting( 'newsletter_text' ) ); ?></p>
|
||||
</div>
|
||||
|
||||
<div class="newsletter-panel__form">
|
||||
<?php gustavoo_portfolio_the_fluent_form( $gustavoo_newsletter_form_id, 'newsletter' ); ?>
|
||||
<?php if ( $gustavoo_privacy_url ) : ?>
|
||||
<p class="form-privacy">
|
||||
<?php
|
||||
printf(
|
||||
/* translators: %s: privacy policy URL. */
|
||||
wp_kses_post( __( 'Você pode cancelar a inscrição a qualquer momento. Consulte a <a href="%s">Política de Privacidade</a>.', 'gustavoo-portfolio' ) ),
|
||||
esc_url( $gustavoo_privacy_url )
|
||||
);
|
||||
?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php
|
||||
/**
|
||||
* Blog post card.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
$gustavoo_categories = get_the_category();
|
||||
$gustavoo_category = $gustavoo_categories ? $gustavoo_categories[0] : null;
|
||||
?>
|
||||
|
||||
<article <?php post_class( 'post-card' ); ?>>
|
||||
<?php if ( has_post_thumbnail() ) : ?>
|
||||
<a class="post-card__media" href="<?php the_permalink(); ?>" tabindex="-1" aria-hidden="true">
|
||||
<?php
|
||||
the_post_thumbnail(
|
||||
'gustavoo-post-card',
|
||||
array(
|
||||
'class' => 'post-card__image',
|
||||
'loading' => 'lazy',
|
||||
'decoding' => 'async',
|
||||
'alt' => '',
|
||||
)
|
||||
);
|
||||
?>
|
||||
</a>
|
||||
<?php endif; ?>
|
||||
|
||||
<div class="post-card__body">
|
||||
<div class="post-card__meta">
|
||||
<?php if ( $gustavoo_category ) : ?>
|
||||
<a class="post-card__category" href="<?php echo esc_url( get_category_link( $gustavoo_category ) ); ?>"><?php echo esc_html( $gustavoo_category->name ); ?></a>
|
||||
<?php endif; ?>
|
||||
<?php gustavoo_portfolio_posted_on(); ?>
|
||||
<span class="reading-time"><?php echo esc_html( gustavoo_portfolio_reading_time() ); ?></span>
|
||||
</div>
|
||||
|
||||
<h2 class="post-card__title"><a href="<?php the_permalink(); ?>"><?php the_title(); ?></a></h2>
|
||||
<p class="post-card__excerpt"><?php echo esc_html( wp_trim_words( get_the_excerpt(), 26 ) ); ?></p>
|
||||
<a class="post-card__more" href="<?php the_permalink(); ?>">
|
||||
<?php esc_html_e( 'Ler artigo', 'gustavoo-portfolio' ); ?> <span aria-hidden="true">→</span>
|
||||
<span class="screen-reader-text">: <?php the_title(); ?></span>
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
@@ -0,0 +1,84 @@
|
||||
<?php
|
||||
/**
|
||||
* Project card.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
$gustavoo_project_id = get_the_ID();
|
||||
$gustavoo_project_url = gustavoo_portfolio_validate_project_url( get_post_meta( $gustavoo_project_id, '_gso_project_url', true ) );
|
||||
$gustavoo_project_client = sanitize_text_field( (string) get_post_meta( $gustavoo_project_id, '_gso_project_client', true ) );
|
||||
$gustavoo_project_year = absint( get_post_meta( $gustavoo_project_id, '_gso_project_year', true ) );
|
||||
$gustavoo_project_link_label = sanitize_text_field( (string) get_post_meta( $gustavoo_project_id, '_gso_project_link_label', true ) );
|
||||
$gustavoo_project_link_label = $gustavoo_project_link_label ?: __( 'Ver projeto', 'gustavoo-portfolio' );
|
||||
$gustavoo_project_types = taxonomy_exists( 'gso_project_type' ) ? get_the_terms( $gustavoo_project_id, 'gso_project_type' ) : array();
|
||||
$gustavoo_project_tech = taxonomy_exists( 'gso_project_tech' ) ? get_the_terms( $gustavoo_project_id, 'gso_project_tech' ) : array();
|
||||
|
||||
if ( ! $gustavoo_project_url ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
|
||||
<article <?php post_class( 'project-card' ); ?>>
|
||||
<a class="project-card__link" href="<?php echo esc_url( $gustavoo_project_url ); ?>" target="_blank" rel="noopener noreferrer external">
|
||||
<figure class="project-card__media">
|
||||
<?php if ( has_post_thumbnail() ) : ?>
|
||||
<?php
|
||||
$gustavoo_thumbnail_id = get_post_thumbnail_id();
|
||||
$gustavoo_thumbnail_alt = get_post_meta( $gustavoo_thumbnail_id, '_wp_attachment_image_alt', true );
|
||||
$gustavoo_thumbnail_alt = $gustavoo_thumbnail_alt ?: sprintf(
|
||||
/* translators: %s: project title. */
|
||||
__( 'Imagem do projeto %s', 'gustavoo-portfolio' ),
|
||||
get_the_title()
|
||||
);
|
||||
|
||||
echo get_the_post_thumbnail(
|
||||
$gustavoo_project_id,
|
||||
'gustavoo-project-card',
|
||||
array(
|
||||
'alt' => $gustavoo_thumbnail_alt,
|
||||
'class' => 'project-card__image',
|
||||
'loading' => 'lazy',
|
||||
'decoding' => 'async',
|
||||
)
|
||||
); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Core image markup.
|
||||
?>
|
||||
<?php else : ?>
|
||||
<span class="project-card__placeholder" aria-hidden="true">
|
||||
<img src="<?php echo esc_url( gustavoo_portfolio_get_image_source( 'logo-mark' ) ); ?>" width="96" height="96" alt="">
|
||||
</span>
|
||||
<?php endif; ?>
|
||||
</figure>
|
||||
|
||||
<div class="project-card__body">
|
||||
<?php if ( ! is_wp_error( $gustavoo_project_types ) && $gustavoo_project_types ) : ?>
|
||||
<p class="project-card__type"><?php echo esc_html( implode( ' · ', wp_list_pluck( $gustavoo_project_types, 'name' ) ) ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<h3 class="project-card__title"><?php the_title(); ?></h3>
|
||||
|
||||
<?php if ( has_excerpt() ) : ?>
|
||||
<p class="project-card__description"><?php echo esc_html( wp_trim_words( get_the_excerpt(), 24 ) ); ?></p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( $gustavoo_project_client || $gustavoo_project_year ) : ?>
|
||||
<p class="project-card__meta">
|
||||
<?php echo esc_html( implode( ' · ', array_filter( array( $gustavoo_project_client, $gustavoo_project_year ? (string) $gustavoo_project_year : '' ) ) ) ); ?>
|
||||
</p>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if ( ! is_wp_error( $gustavoo_project_tech ) && $gustavoo_project_tech ) : ?>
|
||||
<ul class="project-card__tags" aria-label="<?php esc_attr_e( 'Tecnologias', 'gustavoo-portfolio' ); ?>">
|
||||
<?php foreach ( array_slice( $gustavoo_project_tech, 0, 4 ) as $gustavoo_technology ) : ?>
|
||||
<li><?php echo esc_html( $gustavoo_technology->name ); ?></li>
|
||||
<?php endforeach; ?>
|
||||
</ul>
|
||||
<?php endif; ?>
|
||||
|
||||
<span class="project-card__cta">
|
||||
<?php echo esc_html( $gustavoo_project_link_label ); ?> <span aria-hidden="true">↗</span>
|
||||
<span class="screen-reader-text"> <?php esc_html_e( '(abre em uma nova guia)', 'gustavoo-portfolio' ); ?></span>
|
||||
</span>
|
||||
</div>
|
||||
</a>
|
||||
</article>
|
||||
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* Floating WhatsApp action used by the Customizer partial refresh.
|
||||
*
|
||||
* @package Gustavo_Portfolio
|
||||
*/
|
||||
|
||||
gustavoo_portfolio_the_whatsapp_float();
|
||||
@@ -0,0 +1,119 @@
|
||||
{
|
||||
"$schema": "https://schemas.wp.org/trunk/theme.json",
|
||||
"version": 3,
|
||||
"settings": {
|
||||
"appearanceTools": true,
|
||||
"layout": {
|
||||
"contentSize": "760px",
|
||||
"wideSize": "1160px"
|
||||
},
|
||||
"color": {
|
||||
"defaultPalette": false,
|
||||
"palette": [
|
||||
{ "slug": "background", "name": "Fundo", "color": "#071624" },
|
||||
{ "slug": "background-alt", "name": "Fundo alternativo", "color": "#0a1c2d" },
|
||||
{ "slug": "surface", "name": "Superfície", "color": "#0d2438" },
|
||||
{ "slug": "text", "name": "Texto", "color": "#f5f8fa" },
|
||||
{ "slug": "text-soft", "name": "Texto suave", "color": "#b8c5ce" },
|
||||
{ "slug": "brand", "name": "Menta", "color": "#74d5c7" },
|
||||
{ "slug": "brand-strong", "name": "Menta forte", "color": "#50e5cf" }
|
||||
]
|
||||
},
|
||||
"spacing": {
|
||||
"spacingScale": {
|
||||
"steps": 0
|
||||
},
|
||||
"spacingSizes": [
|
||||
{ "slug": "10", "name": "XS", "size": "0.5rem" },
|
||||
{ "slug": "20", "name": "S", "size": "0.75rem" },
|
||||
{ "slug": "30", "name": "M", "size": "1rem" },
|
||||
{ "slug": "40", "name": "L", "size": "1.5rem" },
|
||||
{ "slug": "50", "name": "XL", "size": "2rem" },
|
||||
{ "slug": "60", "name": "2XL", "size": "3rem" },
|
||||
{ "slug": "70", "name": "3XL", "size": "4rem" }
|
||||
],
|
||||
"units": ["px", "rem", "em", "%", "vw", "vh"]
|
||||
},
|
||||
"typography": {
|
||||
"fluid": true,
|
||||
"fontFamilies": [
|
||||
{
|
||||
"fontFamily": "Inter, system-ui, sans-serif",
|
||||
"name": "Inter",
|
||||
"slug": "inter",
|
||||
"fontFace": [
|
||||
{
|
||||
"fontFamily": "Inter",
|
||||
"fontStyle": "normal",
|
||||
"fontWeight": "100 900",
|
||||
"src": ["file:./assets/fonts/inter-variable.woff2"]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"fontFamily": "SFMono-Regular, Consolas, Liberation Mono, monospace",
|
||||
"name": "Monoespaçada",
|
||||
"slug": "mono"
|
||||
}
|
||||
],
|
||||
"fontSizes": [
|
||||
{ "slug": "small", "name": "Pequeno", "size": "0.875rem" },
|
||||
{ "slug": "medium", "name": "Médio", "size": "1rem" },
|
||||
{ "slug": "large", "name": "Grande", "size": "1.25rem" },
|
||||
{ "slug": "x-large", "name": "Muito grande", "size": "clamp(1.75rem, 3vw, 2.75rem)" },
|
||||
{ "slug": "hero", "name": "Hero", "size": "clamp(2.7rem, 5.4vw, 5.3rem)" }
|
||||
]
|
||||
},
|
||||
"border": {
|
||||
"color": true,
|
||||
"radius": true,
|
||||
"style": true,
|
||||
"width": true
|
||||
}
|
||||
},
|
||||
"styles": {
|
||||
"color": {
|
||||
"background": "#071624",
|
||||
"text": "#f5f8fa"
|
||||
},
|
||||
"typography": {
|
||||
"fontFamily": "var(--wp--preset--font-family--inter)",
|
||||
"fontSize": "1.0625rem",
|
||||
"lineHeight": "1.72"
|
||||
},
|
||||
"elements": {
|
||||
"button": {
|
||||
"border": { "radius": "12px" },
|
||||
"color": { "background": "#74d5c7", "text": "#062722" },
|
||||
"typography": { "fontWeight": "700" }
|
||||
},
|
||||
"caption": {
|
||||
"color": { "text": "#879aa9" },
|
||||
"typography": { "fontSize": "0.8rem" }
|
||||
},
|
||||
"heading": {
|
||||
"color": { "text": "#f5f8fa" },
|
||||
"typography": {
|
||||
"fontFamily": "var(--wp--preset--font-family--inter)",
|
||||
"fontWeight": "750",
|
||||
"lineHeight": "1.1"
|
||||
}
|
||||
},
|
||||
"link": {
|
||||
"color": { "text": "#74d5c7" }
|
||||
}
|
||||
},
|
||||
"blocks": {
|
||||
"core/code": {
|
||||
"border": { "color": "rgba(142,190,207,.18)", "radius": "10px", "width": "1px" },
|
||||
"color": { "background": "#040d16", "text": "#d9fdf7" },
|
||||
"typography": { "fontFamily": "var(--wp--preset--font-family--mono)", "fontSize": "0.9rem" }
|
||||
},
|
||||
"core/quote": {
|
||||
"border": { "color": "#74d5c7", "style": "solid", "width": "0 0 0 3px" },
|
||||
"color": { "text": "#b8c5ce" },
|
||||
"spacing": { "padding": { "left": "1.5rem" } }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||