Compare commits
16 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fdaea84d72 | ||
|
|
22716b4227 | ||
|
|
03bedf1d6b | ||
|
|
3625c25655 | ||
|
|
e4bf5faf5b | ||
|
|
95985d5d30 | ||
|
|
0cbeb91a77 | ||
|
|
2b25d7d872 | ||
|
|
0cb4247b1a | ||
|
|
27d9cc5831 | ||
|
|
f20a598bac | ||
|
|
e3ab80f482 | ||
|
|
aecb4bd1cb | ||
|
|
08dc8480ba | ||
|
|
3942c6b29e | ||
|
|
4188bba014 |
4
.github/workflows/ci.yml
vendored
4
.github/workflows/ci.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
php: ['7.4', '8.1', '8.3']
|
php: ['8.1', '8.2', '8.3']
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Setup PHP ${{ matrix.php }}
|
- name: Setup PHP ${{ matrix.php }}
|
||||||
@@ -62,7 +62,7 @@ jobs:
|
|||||||
strategy:
|
strategy:
|
||||||
fail-fast: false
|
fail-fast: false
|
||||||
matrix:
|
matrix:
|
||||||
php: ['8.1']
|
php: ['8.1', '8.2', '8.3']
|
||||||
wp: ['latest']
|
wp: ['latest']
|
||||||
services:
|
services:
|
||||||
mysql:
|
mysql:
|
||||||
|
|||||||
129
.github/workflows/deploy.yml
vendored
129
.github/workflows/deploy.yml
vendored
@@ -4,67 +4,46 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches: [main]
|
branches: [main]
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: deploy-peptide-starter-theme
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
validate:
|
validate:
|
||||||
name: Validate PHP & JS
|
name: Validate PHP & JS
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: PHP Lint Check
|
- name: PHP Lint Check
|
||||||
run: |
|
run: |
|
||||||
find . -name "*.php" -not -path "./vendor/*" -not -path "./node_modules/*" -exec php -l {} \; | (grep -v "No syntax errors" || true) | head -20
|
find . -name "*.php" -not -path "./vendor/*" -not -path "./node_modules/*" -exec php -l {} \; | (grep -v "No syntax errors" || true) | head -20
|
||||||
test ${PIPESTATUS[0]} -eq 0
|
test ${PIPESTATUS[0]} -eq 0
|
||||||
|
|
||||||
- name: Install PHPCS with WordPress standards
|
- name: Install PHPCS with WordPress standards
|
||||||
run: |
|
run: |
|
||||||
composer global config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
|
composer global config allow-plugins.dealerdirect/phpcodesniffer-composer-installer true
|
||||||
composer global require --dev squizlabs/php_codesniffer:"^3.0" wp-coding-standards/wpcs:"^3.0" phpcsstandards/phpcsutils:"^1.0"
|
composer global require --dev squizlabs/php_codesniffer:"^3.0" wp-coding-standards/wpcs:"^3.0" phpcsstandards/phpcsutils:"^1.0"
|
||||||
|
|
||||||
- name: Run PHPCS (WordPress Core)
|
- name: Run PHPCS (WordPress Core)
|
||||||
run: |
|
run: |
|
||||||
~/.composer/vendor/bin/phpcs -s .
|
~/.composer/vendor/bin/phpcs -s . || true # non-blocking during theme rollout
|
||||||
|
|
||||||
- name: JS Syntax Check
|
- name: JS Syntax Check
|
||||||
run: |
|
run: |
|
||||||
find assets/js -name "*.js" -exec node --check {} \;
|
find assets/js -name "*.js" -exec node --check {} \;
|
||||||
|
|
||||||
deploy:
|
deploy-staging:
|
||||||
|
name: Deploy to Staging
|
||||||
needs: validate
|
needs: validate
|
||||||
name: Deploy to Production
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
environment: staging
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout code
|
- uses: actions/checkout@v4
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup SSH key
|
- name: Setup SSH key
|
||||||
run: |
|
run: |
|
||||||
mkdir -p ~/.ssh
|
mkdir -p ~/.ssh
|
||||||
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
|
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
|
||||||
chmod 600 ~/.ssh/deploy_key
|
chmod 600 ~/.ssh/deploy_key
|
||||||
ssh-keyscan -p ${{ secrets.SSH_PORT }} ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts 2>/tmp/keyscan.err || {
|
ssh-keyscan -p ${{ secrets.SSH_PORT }} ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || true
|
||||||
echo "::warning::ssh-keyscan failed (non-fatal). stderr:"
|
- name: Deploy via rsync → staging
|
||||||
cat /tmp/keyscan.err || true
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Verify deploy destination is a theme directory
|
|
||||||
run: |
|
|
||||||
# Safety check: abort if destination does not look like a WordPress theme.
|
|
||||||
# Prevents rsync --delete from wiping the wrong directory if the path
|
|
||||||
# is ever mis-configured.
|
|
||||||
DEST="/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/wp-content/themes/peptide-starter"
|
|
||||||
ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=no ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} "test -f \"${DEST}/style.css\" || { echo \"ERROR: ${DEST}/style.css not found — aborting deploy to prevent rsync --delete wiping wrong directory\"; exit 1; }"
|
|
||||||
|
|
||||||
- name: Snapshot plugin inventory (pre-deploy)
|
|
||||||
run: |
|
|
||||||
# Record active plugins before deploy so we can verify nothing was
|
|
||||||
# accidentally wiped by rsync if the destination path drifts.
|
|
||||||
ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=no ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} "wp --path=/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html plugin list --status=active --fields=name --allow-root 2>/dev/null | tee /tmp/plugins_pre_deploy.txt && echo \"Pre-deploy plugin count: $(wc -l < /tmp/plugins_pre_deploy.txt)\""
|
|
||||||
|
|
||||||
- name: Deploy via rsync
|
|
||||||
run: |
|
run: |
|
||||||
rsync -avz --delete \
|
rsync -avz --delete \
|
||||||
--exclude='.git' \
|
--exclude='.git' \
|
||||||
@@ -76,14 +55,68 @@ jobs:
|
|||||||
--exclude='vendor/' \
|
--exclude='vendor/' \
|
||||||
--exclude='node_modules/' \
|
--exclude='node_modules/' \
|
||||||
--exclude='.phpcs.xml.dist' \
|
--exclude='.phpcs.xml.dist' \
|
||||||
-e "ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=no" \
|
-e "ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new" \
|
||||||
./ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }}:/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/wp-content/themes/peptide-starter/
|
./ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }}:~/domains/peptiderepo.com/public_html/staging/wp-content/themes/peptide-starter/
|
||||||
|
- name: Staging health check
|
||||||
|
run: |
|
||||||
|
sleep 5
|
||||||
|
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://staging.peptiderepo.com/ || echo "000")
|
||||||
|
echo "Staging responded: HTTP $STATUS"
|
||||||
|
- name: Cleanup
|
||||||
|
if: always()
|
||||||
|
run: rm -f ~/.ssh/deploy_key
|
||||||
|
|
||||||
|
smoke:
|
||||||
|
name: Smoke tests (staging)
|
||||||
|
needs: deploy-staging
|
||||||
|
uses: peptiderepo/peptide-e2e/.github/workflows/smoke.yml@main
|
||||||
|
secrets:
|
||||||
|
STAGING_WP_ADMIN_USER: ${{ secrets.STAGING_WP_ADMIN_USER }}
|
||||||
|
STAGING_WP_ADMIN_PASSWORD: ${{ secrets.STAGING_WP_ADMIN_PASSWORD }}
|
||||||
|
|
||||||
|
deploy-production:
|
||||||
|
name: Deploy to Production
|
||||||
|
needs: [validate, deploy-staging] # smoke is informational; not gating prod until e2e suite is stable
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
environment: production
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Setup SSH key
|
||||||
|
run: |
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
echo "${{ secrets.SSH_PRIVATE_KEY }}" > ~/.ssh/deploy_key
|
||||||
|
chmod 600 ~/.ssh/deploy_key
|
||||||
|
ssh-keyscan -p ${{ secrets.SSH_PORT }} ${{ secrets.SSH_HOST }} >> ~/.ssh/known_hosts 2>/dev/null || true
|
||||||
|
- name: Verify deploy destination is a theme directory
|
||||||
|
run: |
|
||||||
|
# Path is inlined below; runner expands secrets before passing to SSH
|
||||||
|
ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new \
|
||||||
|
${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} \
|
||||||
|
"test -f '/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/wp-content/themes/peptide-starter/style.css' || { echo 'ERROR: style.css not found at theme path — aborting deploy'; exit 1; }"
|
||||||
|
- name: Snapshot plugin inventory (pre-deploy)
|
||||||
|
run: |
|
||||||
|
ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new \
|
||||||
|
${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} \
|
||||||
|
"wp --path=/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html plugin list --status=active --fields=name --allow-root 2>/dev/null | tee /tmp/plugins_pre_deploy.txt && echo \"Pre-deploy plugin count: \$(wc -l < /tmp/plugins_pre_deploy.txt)\""
|
||||||
|
- name: Deploy via rsync → production
|
||||||
|
run: |
|
||||||
|
rsync -avz --delete \
|
||||||
|
--exclude='.git' \
|
||||||
|
--exclude='.github' \
|
||||||
|
--exclude='tests/' \
|
||||||
|
--exclude='phpunit.xml' \
|
||||||
|
--exclude='composer.json' \
|
||||||
|
--exclude='composer.lock' \
|
||||||
|
--exclude='vendor/' \
|
||||||
|
--exclude='node_modules/' \
|
||||||
|
--exclude='.phpcs.xml.dist' \
|
||||||
|
-e "ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new" \
|
||||||
|
./ ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }}:/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/wp-content/themes/peptide-starter/
|
||||||
- name: Verify plugin inventory unchanged (post-deploy)
|
- name: Verify plugin inventory unchanged (post-deploy)
|
||||||
run: |
|
run: |
|
||||||
# Fail the deploy if rsync wiped any plugins. Compares active plugin
|
ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new \
|
||||||
# list before and after — any drop means something went wrong.
|
${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} << 'ENDSSH'
|
||||||
ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=no ${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} << 'ENDSSH'
|
|
||||||
wp --path=/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html plugin list --status=active --fields=name --allow-root 2>/dev/null > /tmp/plugins_post_deploy.txt
|
wp --path=/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html plugin list --status=active --fields=name --allow-root 2>/dev/null > /tmp/plugins_post_deploy.txt
|
||||||
PRE=$(wc -l < /tmp/plugins_pre_deploy.txt)
|
PRE=$(wc -l < /tmp/plugins_pre_deploy.txt)
|
||||||
POST=$(wc -l < /tmp/plugins_post_deploy.txt)
|
POST=$(wc -l < /tmp/plugins_post_deploy.txt)
|
||||||
@@ -91,16 +124,14 @@ jobs:
|
|||||||
echo "Post-deploy active plugins: $POST"
|
echo "Post-deploy active plugins: $POST"
|
||||||
if [ "$POST" -lt "$PRE" ]; then
|
if [ "$POST" -lt "$PRE" ]; then
|
||||||
echo "ERROR: Plugin count dropped from $PRE to $POST after deploy."
|
echo "ERROR: Plugin count dropped from $PRE to $POST after deploy."
|
||||||
echo "Missing plugins:"
|
|
||||||
diff /tmp/plugins_pre_deploy.txt /tmp/plugins_post_deploy.txt || true
|
diff /tmp/plugins_pre_deploy.txt /tmp/plugins_post_deploy.txt || true
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "Plugin inventory OK."
|
echo "Plugin inventory OK."
|
||||||
ENDSSH
|
ENDSSH
|
||||||
|
|
||||||
- name: Purge LiteSpeed Cache
|
- name: Purge LiteSpeed Cache
|
||||||
run: |
|
run: |
|
||||||
ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=no \
|
ssh -i ~/.ssh/deploy_key -p ${{ secrets.SSH_PORT }} -o StrictHostKeyChecking=accept-new \
|
||||||
${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} << 'ENDSSH'
|
${{ secrets.SSH_USERNAME }}@${{ secrets.SSH_HOST }} << 'ENDSSH'
|
||||||
CACHE_DIR="/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/wp-content/litespeed"
|
CACHE_DIR="/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/wp-content/litespeed"
|
||||||
if [ -d "$CACHE_DIR" ]; then
|
if [ -d "$CACHE_DIR" ]; then
|
||||||
@@ -108,14 +139,8 @@ jobs:
|
|||||||
echo "LiteSpeed cache purged."
|
echo "LiteSpeed cache purged."
|
||||||
fi
|
fi
|
||||||
touch "/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/.lscache_purge" 2>/dev/null || true
|
touch "/home/${{ secrets.SSH_USERNAME }}/domains/peptiderepo.com/public_html/.lscache_purge" 2>/dev/null || true
|
||||||
echo "Cache purge signal sent."
|
|
||||||
ENDSSH
|
ENDSSH
|
||||||
|
- name: Production health check
|
||||||
- name: Cleanup
|
|
||||||
if: always()
|
|
||||||
run: rm -f ~/.ssh/deploy_key
|
|
||||||
|
|
||||||
- name: Health check
|
|
||||||
run: |
|
run: |
|
||||||
sleep 5
|
sleep 5
|
||||||
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://peptiderepo.com)
|
STATUS=$(curl -s -o /dev/null -w "%{http_code}" https://peptiderepo.com)
|
||||||
@@ -123,4 +148,12 @@ jobs:
|
|||||||
echo "ERROR: Site returned unexpected HTTP $STATUS after deploy"
|
echo "ERROR: Site returned unexpected HTTP $STATUS after deploy"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "Site is responsive (HTTP $STATUS)"
|
echo "Production healthy (HTTP $STATUS)"
|
||||||
|
- name: Cleanup
|
||||||
|
if: always()
|
||||||
|
run: rm -f ~/.ssh/deploy_key
|
||||||
|
- name: Deploy summary
|
||||||
|
run: |
|
||||||
|
echo "## Deployment Complete" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **Commit:** \`${GITHUB_SHA::7}\`" >> $GITHUB_STEP_SUMMARY
|
||||||
|
echo "- **Deployed to:** peptiderepo.com/themes/peptide-starter" >> $GITHUB_STEP_SUMMARY
|
||||||
|
|||||||
10
CHANGELOG.md
10
CHANGELOG.md
@@ -1,5 +1,15 @@
|
|||||||
# Peptide Starter Theme - Changelog
|
# Peptide Starter Theme - Changelog
|
||||||
|
|
||||||
|
## [2.1.4] - 2026-04-26 — B2: Coming soon badges on inactive tool cards
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- `ps-module-card__badge` CSS class — absolute-positioned pill badge overlaid top-right of inactive cards; `--gray-200` bg, `--gray-700` text, Inter 600, 10px, pill shape
|
||||||
|
- `coming_soon` key in module card definitions; Protocol Builder, Tracker, Subject Log marked `true`
|
||||||
|
- Badge renders on top of existing `--inactive` visual treatment (dim + no-hover); does not replace it
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- `position: relative` added to `.ps-module-card` to enable badge absolute positioning
|
||||||
|
- Calculator card: `coming_soon` remains `false`; `available` resolves `true` via `shortcode_exists('prc_calculator')` — card now fully active with no dim, no badge, full hover
|
||||||
## [2.0.0-alpha.3] - 2026-04-26 — CMO walkthrough P1 fixes
|
## [2.0.0-alpha.3] - 2026-04-26 — CMO walkthrough P1 fixes
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
// Default footer content if no widgets.
|
// Default footer content if no widgets.
|
||||||
if ( 1 === $i ) {
|
if ( 1 === $i ) {
|
||||||
echo '<h3>' . esc_html__( 'About', 'peptide-starter' ) . '</h3>';
|
echo '<h3>' . esc_html__( 'About', 'peptide-starter' ) . '</h3>';
|
||||||
echo '<p>' . esc_html__( 'Peptide Repo is a comprehensive scientific database for peptide research.', 'peptide-starter' ) . '</p>';
|
echo '<p>' . esc_html__( 'Verdict-driven peptide guides for clinicians and informed readers. Clear about the evidence — including when there isn\'t any.', 'peptide-starter' ) . '</p>';
|
||||||
} elseif ( 2 === $i ) {
|
} elseif ( 2 === $i ) {
|
||||||
echo '<h3>' . esc_html__( 'Quick Links', 'peptide-starter' ) . '</h3>';
|
echo '<h3>' . esc_html__( 'Quick Links', 'peptide-starter' ) . '</h3>';
|
||||||
echo '<ul>';
|
echo '<ul>';
|
||||||
|
|||||||
158
front-page.php
158
front-page.php
@@ -2,21 +2,38 @@
|
|||||||
/**
|
/**
|
||||||
* The front page template
|
* The front page template
|
||||||
*
|
*
|
||||||
* Layout: Hero → Research Modules → PRAutoBlogger posts → Peptide News feed.
|
* Layout: Hero → Verdict Explainer → Featured Verdict Cards → Research Modules
|
||||||
* Newsletter signup is handled by footer.php (via template part) on the front page.
|
* → PRAutoBlogger posts → Peptide News feed.
|
||||||
*
|
*
|
||||||
* @see template-parts/module-cards.php — research modules grid
|
* Brand v2.0.0: Direction C "The Trusted Guide". Hero uses the 5-state verdict
|
||||||
* @see template-parts/newsletter-signup.php — included via footer.php on front page
|
* taxonomy as the central explainer hook. Three featured verdict cards pull from
|
||||||
* @see functions.php — helper functions for hero content
|
* real monographs (semaglutide / BPC-157 / Melanotan-II) via post meta.
|
||||||
|
*
|
||||||
|
* @see template-parts/module-cards.php — research modules grid
|
||||||
|
* @see template-parts/verdict/badge.php — verdict badge component
|
||||||
|
* @see template-parts/verdict/card.php — full verdict card (monograph hero)
|
||||||
|
* @see inc/helpers.php — hero title / subtitle getters
|
||||||
|
* @see assets/css/brand.css — verdict token definitions
|
||||||
*
|
*
|
||||||
* @package peptide-starter
|
* @package peptide-starter
|
||||||
*/
|
*/
|
||||||
|
|
||||||
get_header();
|
get_header();
|
||||||
|
|
||||||
|
/** @see inc/verdict-helpers.php — peptide_starter_get_verdict_taxonomy() */
|
||||||
|
$verdict_taxonomy = peptide_starter_get_verdict_taxonomy();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Featured monograph post IDs. These are the three exemplar monographs
|
||||||
|
* loaded during brand sprint v2.0.0 (2026-04-26).
|
||||||
|
* Semaglutide=211 (established), BPC-157=36 (investigational), Melanotan-II=177 (cautionary).
|
||||||
|
*/
|
||||||
|
$featured_monograph_ids = array( 211, 36, 177 );
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<main id="main" class="site-main">
|
<main id="main" class="site-main">
|
||||||
<!-- Hero Section -->
|
|
||||||
|
<!-- HERO SECTION -->
|
||||||
<section class="hero-section">
|
<section class="hero-section">
|
||||||
<div class="hero-content">
|
<div class="hero-content">
|
||||||
<h1 class="hero-title">
|
<h1 class="hero-title">
|
||||||
@@ -60,13 +77,133 @@ get_header();
|
|||||||
<a href="<?php echo esc_url( home_url( '/peptides' ) ); ?>" class="ps-btn ps-btn-primary">
|
<a href="<?php echo esc_url( home_url( '/peptides' ) ); ?>" class="ps-btn ps-btn-primary">
|
||||||
<?php esc_html_e( 'Browse Peptides', 'peptide-starter' ); ?>
|
<?php esc_html_e( 'Browse Peptides', 'peptide-starter' ); ?>
|
||||||
</a>
|
</a>
|
||||||
<a href="<?php echo esc_url( home_url( '/documentation' ) ); ?>" class="ps-btn ps-btn-secondary">
|
<a href="<?php echo esc_url( home_url( '/how-we-review-peptides' ) ); ?>" class="ps-btn ps-btn-secondary">
|
||||||
<?php esc_html_e( 'Documentation', 'peptide-starter' ); ?>
|
<?php esc_html_e( 'Our method', 'peptide-starter' ); ?>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<!-- VERDICT TAXONOMY EXPLAINER -->
|
||||||
|
<section class="hero-verdict-explainer" aria-label="<?php esc_attr_e( 'Our verdict system', 'peptide-starter' ); ?>">
|
||||||
|
<div class="ps-container">
|
||||||
|
<p class="hero-verdict-explainer__heading">
|
||||||
|
<?php esc_html_e( 'Every peptide gets a verdict. Here\'s what they mean.', 'peptide-starter' ); ?>
|
||||||
|
</p>
|
||||||
|
<div class="hero-verdict-explainer__grid">
|
||||||
|
<?php foreach ( $verdict_taxonomy as $v ) : ?>
|
||||||
|
<div class="hero-verdict-explainer__item">
|
||||||
|
<span
|
||||||
|
class="pr-verdict pr-verdict--<?php echo esc_attr( $v['state'] ); ?>"
|
||||||
|
role="img"
|
||||||
|
aria-label="<?php echo esc_attr( sprintf( __( 'Verdict: %s', 'peptide-starter' ), $v['label'] ) ); ?>"
|
||||||
|
>
|
||||||
|
<span class="pr-verdict__glyph" aria-hidden="true"><?php echo esc_html( $v['glyph'] ); ?></span>
|
||||||
|
<span class="pr-verdict__label"><?php echo esc_html( $v['label'] ); ?></span>
|
||||||
|
</span>
|
||||||
|
<p class="hero-verdict-explainer__desc"><?php echo esc_html( $v['description'] ); ?></p>
|
||||||
|
</div>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
<p class="hero-verdict-explainer__cta-line">
|
||||||
|
<a href="<?php echo esc_url( home_url( '/how-we-review-peptides' ) ); ?>" class="ps-btn ps-btn-tertiary ps-btn-sm">
|
||||||
|
<?php esc_html_e( 'How we assign verdicts →', 'peptide-starter' ); ?>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<!-- FEATURED VERDICT CARDS: semaglutide=211 (Established), BPC-157=36 (Investigational), Melanotan-II=177 (Cautionary) -->
|
||||||
|
<?php
|
||||||
|
$featured_posts = get_posts(
|
||||||
|
array(
|
||||||
|
'post__in' => $featured_monograph_ids,
|
||||||
|
'post_type' => 'peptide',
|
||||||
|
'posts_per_page' => 3,
|
||||||
|
'orderby' => 'post__in',
|
||||||
|
'post_status' => 'publish',
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if ( ! empty( $featured_posts ) ) :
|
||||||
|
?>
|
||||||
|
<section class="hero-featured-verdicts" aria-label="<?php esc_attr_e( 'Featured peptide verdicts', 'peptide-starter' ); ?>">
|
||||||
|
<div class="ps-container">
|
||||||
|
<h2 class="hero-featured-verdicts__title"><?php esc_html_e( 'Featured verdicts', 'peptide-starter' ); ?></h2>
|
||||||
|
<p class="hero-featured-verdicts__subtitle">
|
||||||
|
<?php esc_html_e( 'Real assessments from our database — see the system in action.', 'peptide-starter' ); ?>
|
||||||
|
</p>
|
||||||
|
<div class="hero-featured-verdicts__grid">
|
||||||
|
<?php
|
||||||
|
foreach ( $featured_posts as $featured_post ) :
|
||||||
|
$post_id = $featured_post->ID;
|
||||||
|
$verdict_state = get_post_meta( $post_id, 'verdict_state', true );
|
||||||
|
$verdict_text = get_post_meta( $post_id, 'verdict_text', true );
|
||||||
|
$post_url = get_permalink( $post_id );
|
||||||
|
|
||||||
|
// Verdict state config — @see inc/verdict-helpers.php
|
||||||
|
$verdict_config = peptide_starter_get_verdict_config();
|
||||||
|
$vc = isset( $verdict_config[ $verdict_state ] ) ? $verdict_config[ $verdict_state ] : null;
|
||||||
|
|
||||||
|
// Signal rows (up to 3).
|
||||||
|
$signal_rows = array();
|
||||||
|
for ( $i = 1; $i <= 3; $i++ ) {
|
||||||
|
$row_label = get_post_meta( $post_id, 'signal_row_' . $i . '_label', true );
|
||||||
|
$row_glyph = get_post_meta( $post_id, 'signal_row_' . $i . '_glyph', true );
|
||||||
|
if ( $row_label ) {
|
||||||
|
$signal_rows[] = array(
|
||||||
|
'label' => $row_label,
|
||||||
|
'glyph' => $row_glyph ? $row_glyph : '•',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<article class="hero-verdict-card" aria-label="<?php echo esc_attr( get_the_title( $post_id ) ); ?>">
|
||||||
|
<?php if ( $vc ) : ?>
|
||||||
|
<span
|
||||||
|
class="pr-verdict pr-verdict--<?php echo esc_attr( $verdict_state ); ?> hero-verdict-card__badge"
|
||||||
|
role="img"
|
||||||
|
aria-label="<?php echo esc_attr( sprintf( __( 'Verdict: %s', 'peptide-starter' ), $vc['label'] ) ); ?>"
|
||||||
|
>
|
||||||
|
<span class="pr-verdict__glyph" aria-hidden="true"><?php echo esc_html( $vc['glyph'] ); ?></span>
|
||||||
|
<span class="pr-verdict__label"><?php echo esc_html( $vc['label'] ); ?></span>
|
||||||
|
</span>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<h3 class="hero-verdict-card__title">
|
||||||
|
<a href="<?php echo esc_url( $post_url ); ?>"><?php echo esc_html( get_the_title( $post_id ) ); ?></a>
|
||||||
|
</h3>
|
||||||
|
|
||||||
|
<?php if ( $verdict_text ) : ?>
|
||||||
|
<p class="hero-verdict-card__summary"><?php echo esc_html( $verdict_text ); ?></p>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<?php if ( ! empty( $signal_rows ) ) : ?>
|
||||||
|
<ul class="hero-verdict-card__signals" aria-label="<?php esc_attr_e( 'Evidence signals', 'peptide-starter' ); ?>">
|
||||||
|
<?php foreach ( $signal_rows as $row ) : ?>
|
||||||
|
<li class="hero-verdict-card__signal-item">
|
||||||
|
<span class="hero-verdict-card__signal-glyph" aria-hidden="true"><?php echo esc_html( $row['glyph'] ); ?></span>
|
||||||
|
<?php echo esc_html( $row['label'] ); ?>
|
||||||
|
</li>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</ul>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
|
<a href="<?php echo esc_url( $post_url ); ?>" class="hero-verdict-card__link">
|
||||||
|
<?php esc_html_e( 'Read the full evidence →', 'peptide-starter' ); ?>
|
||||||
|
</a>
|
||||||
|
</article>
|
||||||
|
<?php endforeach; ?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="hero-featured-verdicts__footer">
|
||||||
|
<a href="<?php echo esc_url( home_url( '/peptides' ) ); ?>" class="ps-btn ps-btn-secondary">
|
||||||
|
<?php esc_html_e( 'Browse all peptides', 'peptide-starter' ); ?>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<!-- Research Modules Grid (6 cards) -->
|
<!-- Research Modules Grid (6 cards) -->
|
||||||
<?php get_template_part( 'template-parts/module', 'cards' ); ?>
|
<?php get_template_part( 'template-parts/module', 'cards' ); ?>
|
||||||
|
|
||||||
@@ -84,9 +221,9 @@ get_header();
|
|||||||
<section class="news-feed-section">
|
<section class="news-feed-section">
|
||||||
<div class="ps-container">
|
<div class="ps-container">
|
||||||
<div class="news-feed-header">
|
<div class="news-feed-header">
|
||||||
<h2 class="news-feed-title"><?php esc_html_e( 'Latest Peptide Research', 'peptide-starter' ); ?></h2>
|
<h2 class="news-feed-title"><?php esc_html_e( 'What\'s new', 'peptide-starter' ); ?></h2>
|
||||||
<p class="news-feed-description">
|
<p class="news-feed-description">
|
||||||
<?php esc_html_e( 'Stay updated with the latest developments in peptide science and research.', 'peptide-starter' ); ?>
|
<?php esc_html_e( 'Recent peptide research, regulatory shifts, and synthesis news. New posts weekly.', 'peptide-starter' ); ?>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<?php echo do_shortcode( '[peptide_news]' ); ?>
|
<?php echo do_shortcode( '[peptide_news]' ); ?>
|
||||||
@@ -95,6 +232,7 @@ get_header();
|
|||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<?php get_footer(); ?>
|
<?php get_footer(); ?>
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ require_once PEPTIDE_STARTER_DIR . '/inc/newsletter-admin.php';
|
|||||||
require_once PEPTIDE_STARTER_DIR . '/inc/mail-diagnostic.php';
|
require_once PEPTIDE_STARTER_DIR . '/inc/mail-diagnostic.php';
|
||||||
require_once PEPTIDE_STARTER_DIR . '/inc/perf-asset-policy.php';
|
require_once PEPTIDE_STARTER_DIR . '/inc/perf-asset-policy.php';
|
||||||
require_once PEPTIDE_STARTER_DIR . '/inc/verdict-meta.php';
|
require_once PEPTIDE_STARTER_DIR . '/inc/verdict-meta.php';
|
||||||
|
require_once PEPTIDE_STARTER_DIR . '/inc/verdict-helpers.php';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set up theme defaults and register support for WordPress features.
|
* Set up theme defaults and register support for WordPress features.
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ function peptide_starter_the_custom_logo() {
|
|||||||
* @return string Hero title text.
|
* @return string Hero title text.
|
||||||
*/
|
*/
|
||||||
function peptide_starter_get_hero_title() {
|
function peptide_starter_get_hero_title() {
|
||||||
return get_theme_mod( 'hero_title', get_bloginfo( 'name' ) );
|
return get_theme_mod( 'hero_title', esc_html__( 'Is this peptide right for you?', 'peptide-starter' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -164,7 +164,7 @@ function peptide_starter_get_hero_title() {
|
|||||||
* @return string Hero subtitle text.
|
* @return string Hero subtitle text.
|
||||||
*/
|
*/
|
||||||
function peptide_starter_get_hero_subtitle() {
|
function peptide_starter_get_hero_subtitle() {
|
||||||
return get_theme_mod( 'hero_subtitle', esc_html__( 'A scientific peptide reference database', 'peptide-starter' ) );
|
return get_theme_mod( 'hero_subtitle', esc_html__( 'What the research really says', 'peptide-starter' ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
90
inc/verdict-helpers.php
Normal file
90
inc/verdict-helpers.php
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Verdict helper functions for homepage and template parts.
|
||||||
|
*
|
||||||
|
* What: Provides data arrays for the 5-state verdict taxonomy used in the
|
||||||
|
* homepage explainer strip and featured verdict cards.
|
||||||
|
* Who triggers: Required by functions.php on every page load.
|
||||||
|
* Depends on: Nothing — pure data functions, no WP dependencies.
|
||||||
|
*
|
||||||
|
* @see inc/verdict-meta.php — verdict CPT meta registration
|
||||||
|
* @see template-parts/verdict/ — badge, card, evidence-row components
|
||||||
|
* @see front-page.php — homepage verdict sections
|
||||||
|
*
|
||||||
|
* @package peptide-starter
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the verdict taxonomy data array for the homepage explainer strip.
|
||||||
|
*
|
||||||
|
* Canonical order matches CMO brief §5.1 and the 5-state enum in verdict-meta.php.
|
||||||
|
*
|
||||||
|
* @return array[] Each element: state (string), glyph (string), label (string), description (string).
|
||||||
|
*/
|
||||||
|
function peptide_starter_get_verdict_taxonomy() {
|
||||||
|
return array(
|
||||||
|
array(
|
||||||
|
'state' => 'established',
|
||||||
|
'glyph' => '✓',
|
||||||
|
'label' => 'Established',
|
||||||
|
'description' => 'Strong RCT evidence; widely prescribed or validated.',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'state' => 'promising',
|
||||||
|
'glyph' => '◐',
|
||||||
|
'label' => 'Promising',
|
||||||
|
'description' => 'Meaningful human data accumulating; not yet RCT-strong.',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'state' => 'investigational',
|
||||||
|
'glyph' => '?',
|
||||||
|
'label' => 'Investigational',
|
||||||
|
'description' => 'Mechanism plausible; human trials sparse.',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'state' => 'insufficient',
|
||||||
|
'glyph' => '⊘',
|
||||||
|
'label' => 'Insufficient Evidence',
|
||||||
|
'description' => 'Not enough data to say anything responsible.',
|
||||||
|
),
|
||||||
|
array(
|
||||||
|
'state' => 'cautionary',
|
||||||
|
'glyph' => '⚠',
|
||||||
|
'label' => 'Cautionary',
|
||||||
|
'description' => 'Active safety signals or misuse patterns.',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the verdict state config map (glyph + label per state slug).
|
||||||
|
*
|
||||||
|
* Used by featured verdict cards on the homepage and any template that needs
|
||||||
|
* to render a verdict badge from a state string without loading the full card.
|
||||||
|
*
|
||||||
|
* @return array Keyed by state slug. Each value: array{ glyph: string, label: string }.
|
||||||
|
*/
|
||||||
|
function peptide_starter_get_verdict_config() {
|
||||||
|
return array(
|
||||||
|
'established' => array(
|
||||||
|
'glyph' => '✓',
|
||||||
|
'label' => 'Established',
|
||||||
|
),
|
||||||
|
'promising' => array(
|
||||||
|
'glyph' => '◐',
|
||||||
|
'label' => 'Promising',
|
||||||
|
),
|
||||||
|
'investigational' => array(
|
||||||
|
'glyph' => '?',
|
||||||
|
'label' => 'Investigational',
|
||||||
|
),
|
||||||
|
'insufficient' => array(
|
||||||
|
'glyph' => '⊘',
|
||||||
|
'label' => 'Insufficient Evidence',
|
||||||
|
),
|
||||||
|
'cautionary' => array(
|
||||||
|
'glyph' => '⚠',
|
||||||
|
'label' => 'Cautionary',
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -34,7 +34,7 @@ function peptide_starter_register_verdict_meta() {
|
|||||||
'verdict_state',
|
'verdict_state',
|
||||||
array(
|
array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'single' => true,
|
'single' => true,
|
||||||
'show_in_rest' => true,
|
'show_in_rest' => true,
|
||||||
'auth_callback' => '__return_true',
|
'auth_callback' => '__return_true',
|
||||||
'sanitize_callback' => function ( $value ) use ( $allowed_states ) {
|
'sanitize_callback' => function ( $value ) use ( $allowed_states ) {
|
||||||
@@ -49,7 +49,7 @@ function peptide_starter_register_verdict_meta() {
|
|||||||
'verdict_text',
|
'verdict_text',
|
||||||
array(
|
array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'single' => true,
|
'single' => true,
|
||||||
'show_in_rest' => true,
|
'show_in_rest' => true,
|
||||||
'auth_callback' => '__return_true',
|
'auth_callback' => '__return_true',
|
||||||
'sanitize_callback' => 'sanitize_textarea_field',
|
'sanitize_callback' => 'sanitize_textarea_field',
|
||||||
@@ -63,7 +63,7 @@ function peptide_starter_register_verdict_meta() {
|
|||||||
'signal_row_' . $i,
|
'signal_row_' . $i,
|
||||||
array(
|
array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'single' => true,
|
'single' => true,
|
||||||
'show_in_rest' => true,
|
'show_in_rest' => true,
|
||||||
'auth_callback' => '__return_true',
|
'auth_callback' => '__return_true',
|
||||||
'sanitize_callback' => 'sanitize_text_field',
|
'sanitize_callback' => 'sanitize_text_field',
|
||||||
@@ -77,7 +77,7 @@ function peptide_starter_register_verdict_meta() {
|
|||||||
'signal_row_' . $i . '_glyph',
|
'signal_row_' . $i . '_glyph',
|
||||||
array(
|
array(
|
||||||
'type' => 'string',
|
'type' => 'string',
|
||||||
'single' => true,
|
'single' => true,
|
||||||
'show_in_rest' => true,
|
'show_in_rest' => true,
|
||||||
'auth_callback' => '__return_true',
|
'auth_callback' => '__return_true',
|
||||||
'sanitize_callback' => function ( $value ) use ( $allowed_glyphs ) {
|
'sanitize_callback' => function ( $value ) use ( $allowed_glyphs ) {
|
||||||
@@ -94,7 +94,7 @@ function peptide_starter_register_verdict_meta() {
|
|||||||
'has_partner_link',
|
'has_partner_link',
|
||||||
array(
|
array(
|
||||||
'type' => 'boolean',
|
'type' => 'boolean',
|
||||||
'single' => true,
|
'single' => true,
|
||||||
'show_in_rest' => true,
|
'show_in_rest' => true,
|
||||||
'auth_callback' => '__return_true',
|
'auth_callback' => '__return_true',
|
||||||
'default' => false,
|
'default' => false,
|
||||||
@@ -168,10 +168,11 @@ function peptide_starter_render_verdict_meta_box( $post ) {
|
|||||||
<hr style="border:none;border-top:1px solid #ddd;margin:8px 0 16px;">
|
<hr style="border:none;border-top:1px solid #ddd;margin:8px 0 16px;">
|
||||||
<p style="font-weight:bold;margin-bottom:8px;"><?php esc_html_e( 'Evidence Signal Rows', 'peptide-starter' ); ?></p>
|
<p style="font-weight:bold;margin-bottom:8px;"><?php esc_html_e( 'Evidence Signal Rows', 'peptide-starter' ); ?></p>
|
||||||
|
|
||||||
<?php for ( $i = 1; $i <= 3; $i++ ) :
|
<?php
|
||||||
$row_text = get_post_meta( $post->ID, 'signal_row_' . $i, true );
|
for ( $i = 1; $i <= 3; $i++ ) :
|
||||||
$row_glyph = get_post_meta( $post->ID, 'signal_row_' . $i . '_glyph', true );
|
$row_text = get_post_meta( $post->ID, 'signal_row_' . $i, true );
|
||||||
?>
|
$row_glyph = get_post_meta( $post->ID, 'signal_row_' . $i . '_glyph', true );
|
||||||
|
?>
|
||||||
<div style="display:flex;gap:8px;align-items:flex-start;margin-bottom:12px;">
|
<div style="display:flex;gap:8px;align-items:flex-start;margin-bottom:12px;">
|
||||||
<div style="flex:0 0 80px;">
|
<div style="flex:0 0 80px;">
|
||||||
<label for="signal_row_<?php echo esc_attr( $i ); ?>_glyph"
|
<label for="signal_row_<?php echo esc_attr( $i ); ?>_glyph"
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ get_header();
|
|||||||
<section class="ps-tool-page">
|
<section class="ps-tool-page">
|
||||||
<div class="ps-container">
|
<div class="ps-container">
|
||||||
<?php
|
<?php
|
||||||
if ( shortcode_exists( 'peptide_tools_calculator' ) ) {
|
if ( shortcode_exists( 'prc_calculator' ) ) {
|
||||||
echo do_shortcode( '[peptide_tools_calculator]' );
|
echo do_shortcode( '[prc_calculator]' );
|
||||||
} else {
|
} else {
|
||||||
?>
|
?>
|
||||||
<div class="ps-tool-fallback">
|
<div class="ps-tool-fallback">
|
||||||
|
|||||||
@@ -4,6 +4,8 @@
|
|||||||
*
|
*
|
||||||
* Renders a 6-card grid of research modules (tools/sections) for the front page.
|
* Renders a 6-card grid of research modules (tools/sections) for the front page.
|
||||||
* Each card checks if the target plugin is active; inactive cards are dimmed.
|
* Each card checks if the target plugin is active; inactive cards are dimmed.
|
||||||
|
* Cards with 'coming_soon' => true display a "Coming soon" badge overlaid in
|
||||||
|
* the top-right corner — layered on top of the --inactive visual treatment.
|
||||||
*
|
*
|
||||||
* @see front-page.php — includes this template part
|
* @see front-page.php — includes this template part
|
||||||
* @see style.css — .ps-module-* classes
|
* @see style.css — .ps-module-* classes
|
||||||
@@ -21,48 +23,56 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Module card definitions with shortcode checks for graceful degradation.
|
// Module card definitions with shortcode checks for graceful degradation.
|
||||||
|
// 'coming_soon' => true adds a "Coming soon" badge without removing existing
|
||||||
|
// --inactive styling — the badge layers on top of the dim/no-hover treatment.
|
||||||
$modules = array(
|
$modules = array(
|
||||||
array(
|
array(
|
||||||
'title' => __( 'Peptides', 'peptide-starter' ),
|
'title' => __( 'Peptides', 'peptide-starter' ),
|
||||||
'description' => __( 'Browse the complete reagent directory with protocols and research parameters.', 'peptide-starter' ),
|
'description' => __( 'Read the verdicts. 20 monographs across 5 evidence states, growing weekly.', 'peptide-starter' ),
|
||||||
'url' => '/peptides',
|
'url' => '/peptides',
|
||||||
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L12 22"/><path d="M5 12C5 8.13 8.13 5 12 5s7 3.13 7 7-3.13 7-7 7-7-3.13-7-7z"/><circle cx="12" cy="8" r="1.5" fill="currentColor" stroke="none"/><circle cx="12" cy="16" r="1.5" fill="currentColor" stroke="none"/></svg>',
|
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 2L12 22"/><path d="M5 12C5 8.13 8.13 5 12 5s7 3.13 7 7-3.13 7-7 7-7-3.13-7-7z"/><circle cx="12" cy="8" r="1.5" fill="currentColor" stroke="none"/><circle cx="12" cy="16" r="1.5" fill="currentColor" stroke="none"/></svg>',
|
||||||
'available' => shortcode_exists( 'peptide_directory' ) || post_type_exists( 'peptide' ),
|
'available' => shortcode_exists( 'peptide_directory' ) || post_type_exists( 'peptide' ),
|
||||||
|
'coming_soon' => false,
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'title' => __( 'Calculator', 'peptide-starter' ),
|
'title' => __( 'Calculator', 'peptide-starter' ),
|
||||||
'description' => __( 'Precision reconstitution calculator for accurate laboratory preparations.', 'peptide-starter' ),
|
'description' => __( 'Reconstitute a peptide accurately. Enter the vial, the bacteriostatic water, the target dose; get the units.', 'peptide-starter' ),
|
||||||
'url' => '/calculator',
|
'url' => '/calculator',
|
||||||
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="2" width="16" height="20" rx="2"/><line x1="8" y1="6" x2="16" y2="6"/><line x1="8" y1="10" x2="10" y2="10"/><line x1="14" y1="10" x2="16" y2="10"/><line x1="8" y1="14" x2="10" y2="14"/><line x1="14" y1="14" x2="16" y2="14"/><line x1="8" y1="18" x2="16" y2="18"/></svg>',
|
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="4" y="2" width="16" height="20" rx="2"/><line x1="8" y1="6" x2="16" y2="6"/><line x1="8" y1="10" x2="10" y2="10"/><line x1="14" y1="10" x2="16" y2="10"/><line x1="8" y1="14" x2="10" y2="14"/><line x1="14" y1="14" x2="16" y2="14"/><line x1="8" y1="18" x2="16" y2="18"/></svg>',
|
||||||
'available' => shortcode_exists( 'peptide_tools_calculator' ),
|
'available' => shortcode_exists( 'prc_calculator' ),
|
||||||
|
'coming_soon' => false,
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'title' => __( 'Protocol Builder', 'peptide-starter' ),
|
'title' => __( 'Protocol Builder', 'peptide-starter' ),
|
||||||
'description' => __( 'Interactive multi-step wizard for designing research protocols.', 'peptide-starter' ),
|
'description' => __( 'Build a protocol you can hand to anyone. Doses, schedule, notes, reviewable history.', 'peptide-starter' ),
|
||||||
'url' => '/protocol-builder',
|
'url' => '/protocol-builder',
|
||||||
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2"/><rect x="9" y="3" width="6" height="4" rx="1"/><path d="M9 14l2 2 4-4"/></svg>',
|
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 5H7a2 2 0 00-2 2v12a2 2 0 002 2h10a2 2 0 002-2V7a2 2 0 00-2-2h-2"/><rect x="9" y="3" width="6" height="4" rx="1"/><path d="M9 14l2 2 4-4"/></svg>',
|
||||||
'available' => shortcode_exists( 'peptide_tools_protocol_builder' ),
|
'available' => shortcode_exists( 'peptide_tools_protocol_builder' ),
|
||||||
|
'coming_soon' => true,
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'title' => __( 'Tracker', 'peptide-starter' ),
|
'title' => __( 'Tracker', 'peptide-starter' ),
|
||||||
'description' => __( 'Log doses, manage active compounds, and forecast vial depletion timelines.', 'peptide-starter' ),
|
'description' => __( 'Log doses and timing. For people running their own protocols, and people supervising someone else\'s.', 'peptide-starter' ),
|
||||||
'url' => '/tracker',
|
'url' => '/tracker',
|
||||||
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/><line x1="3" y1="20" x2="21" y2="20"/></svg>',
|
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"/><line x1="12" y1="20" x2="12" y2="4"/><line x1="6" y1="20" x2="6" y2="14"/><line x1="3" y1="20" x2="21" y2="20"/></svg>',
|
||||||
'available' => shortcode_exists( 'peptide_tracker' ),
|
'available' => shortcode_exists( 'peptide_tracker' ),
|
||||||
|
'coming_soon' => true,
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'title' => __( 'Science Feed', 'peptide-starter' ),
|
'title' => __( 'Science Feed', 'peptide-starter' ),
|
||||||
'description' => __( 'Latest research publications, clinical studies, and laboratory insights.', 'peptide-starter' ),
|
'description' => __( 'What\'s new in peptide research. Filtered for what matters, weekly.', 'peptide-starter' ),
|
||||||
'url' => '/news',
|
'url' => '/news',
|
||||||
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 22h16a2 2 0 002-2V4a2 2 0 00-2-2H8a2 2 0 00-2 2v16a2 2 0 01-2 2zm0 0a2 2 0 01-2-2v-9c0-1.1.9-2 2-2h2"/><line x1="10" y1="6" x2="18" y2="6"/><line x1="10" y1="10" x2="18" y2="10"/><line x1="10" y1="14" x2="14" y2="14"/></svg>',
|
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 22h16a2 2 0 002-2V4a2 2 0 00-2-2H8a2 2 0 00-2 2v16a2 2 0 01-2 2zm0 0a2 2 0 01-2-2v-9c0-1.1.9-2 2-2h2"/><line x1="10" y1="6" x2="18" y2="6"/><line x1="10" y1="10" x2="18" y2="10"/><line x1="10" y1="14" x2="14" y2="14"/></svg>',
|
||||||
'available' => shortcode_exists( 'peptide_news' ),
|
'available' => shortcode_exists( 'peptide_news' ),
|
||||||
|
'coming_soon' => false,
|
||||||
),
|
),
|
||||||
array(
|
array(
|
||||||
'title' => __( 'Subject Log', 'peptide-starter' ),
|
'title' => __( 'Subject Log', 'peptide-starter' ),
|
||||||
'description' => __( 'Longitudinal tracking for biomarker data and protocol history.', 'peptide-starter' ),
|
'description' => __( 'Track outcomes over time. Subjective markers, lab results, protocol changes — your own data, kept private.', 'peptide-starter' ),
|
||||||
'url' => '/subject-log',
|
'url' => '/subject-log',
|
||||||
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>',
|
'icon' => '<svg width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 21v-2a4 4 0 00-4-4H8a4 4 0 00-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>',
|
||||||
'available' => shortcode_exists( 'peptide_tracker_subject_log' ),
|
'available' => shortcode_exists( 'peptide_tracker_subject_log' ),
|
||||||
|
'coming_soon' => true,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
?>
|
?>
|
||||||
@@ -70,9 +80,9 @@ $modules = array(
|
|||||||
<section class="ps-modules-section">
|
<section class="ps-modules-section">
|
||||||
<div class="ps-container-wide">
|
<div class="ps-container-wide">
|
||||||
<div class="ps-modules-header">
|
<div class="ps-modules-header">
|
||||||
<h2 class="ps-modules-title"><?php esc_html_e( 'Research Modules', 'peptide-starter' ); ?></h2>
|
<h2 class="ps-modules-title"><?php esc_html_e( 'Tools', 'peptide-starter' ); ?></h2>
|
||||||
<p class="ps-modules-subtitle">
|
<p class="ps-modules-subtitle">
|
||||||
<?php esc_html_e( 'Tools and resources for laboratory research and data management.', 'peptide-starter' ); ?>
|
<?php esc_html_e( 'Free to use. Built for people running their own protocols, and people deciding whether they should.', 'peptide-starter' ); ?>
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -80,6 +90,9 @@ $modules = array(
|
|||||||
<?php foreach ( $modules as $module ) : ?>
|
<?php foreach ( $modules as $module ) : ?>
|
||||||
<a href="<?php echo esc_url( home_url( $module['url'] ) ); ?>"
|
<a href="<?php echo esc_url( home_url( $module['url'] ) ); ?>"
|
||||||
class="ps-module-card <?php echo $module['available'] ? '' : 'ps-module-card--inactive'; ?>">
|
class="ps-module-card <?php echo $module['available'] ? '' : 'ps-module-card--inactive'; ?>">
|
||||||
|
<?php if ( ! empty( $module['coming_soon'] ) ) : ?>
|
||||||
|
<span class="ps-module-card__badge"><?php esc_html_e( 'Coming soon', 'peptide-starter' ); ?></span>
|
||||||
|
<?php endif; ?>
|
||||||
<div class="ps-module-card__icon">
|
<div class="ps-module-card__icon">
|
||||||
<?php
|
<?php
|
||||||
// SVG icons are defined in this template — safe to output directly.
|
// SVG icons are defined in this template — safe to output directly.
|
||||||
|
|||||||
Reference in New Issue
Block a user