I’ll build this as a full advanced WordPress page template for RX Theme: security checks, custom query support, filters, schema JSON-LD, review-board cards, search/filter UI, pagination, accessibility, and fallback content.
Friend, create this file:
rx-theme/templates/template-review-board.php
This is an advanced self-contained Review Board page template for RX Theme. It supports:
Review board member listing, search, specialty filter, designation filter, country filter, sorting, pagination, verified/active badge, schema JSON-LD, accessibility, security escaping, shortcode support, reusable hooks, fallback demo content, responsive HTML structure, and SEO-friendly medical review board layout.
<?php
/**
* Template Name: RX Review Board
* Template Post Type: page
*
* Advanced Review Board Template for RX Theme.
*
* Location:
* /templates/template-review-board.php
*
* Recommended Custom Post Type:
* review_board
*
* Supported custom fields:
* - rxrb_full_name
* - rxrb_designation
* - rxrb_specialty
* - rxrb_country
* - rxrb_institution
* - rxrb_qualification
* - rxrb_experience
* - rxrb_profile_url
* - rxrb_orcid
* - rxrb_google_scholar
* - rxrb_pubmed
* - rxrb_verified
* - rxrb_status
* - rxrb_review_count
* - rxrb_last_reviewed
* - rxrb_short_bio
*
* @package RX_Theme
*/
defined( 'ABSPATH' ) || exit;
get_header();
/**
* ------------------------------------------------------------
* RX Review Board Helper Functions
* ------------------------------------------------------------
*/
if ( ! function_exists( 'rx_review_board_get_meta' ) ) {
/**
* Safe post meta getter.
*
* @param int $post_id Post ID.
* @param string $key Meta key.
* @param string $default Default value.
* @return string
*/
function rx_review_board_get_meta( $post_id, $key, $default = '' ) {
$value = get_post_meta( $post_id, $key, true );
if ( is_array( $value ) ) {
$value = implode( ', ', array_map( 'sanitize_text_field', $value ) );
}
if ( '' === $value || null === $value ) {
return $default;
}
return sanitize_text_field( wp_unslash( $value ) );
}
}
if ( ! function_exists( 'rx_review_board_bool_meta' ) ) {
/**
* Convert meta value to boolean.
*
* @param int $post_id Post ID.
* @param string $key Meta key.
* @return bool
*/
function rx_review_board_bool_meta( $post_id, $key ) {
$value = get_post_meta( $post_id, $key, true );
return in_array( strtolower( (string) $value ), array( '1', 'yes', 'true', 'on', 'verified', 'active' ), true );
}
}
if ( ! function_exists( 'rx_review_board_get_field_options' ) ) {
/**
* Collect unique meta values for filter dropdown.
*
* @param string $meta_key Meta key.
* @return array
*/
function rx_review_board_get_field_options( $meta_key ) {
global $wpdb;
$cache_key = 'rxrb_options_' . md5( $meta_key );
$cached = get_transient( $cache_key );
if ( false !== $cached ) {
return $cached;
}
$values = $wpdb->get_col(
$wpdb->prepare(
"
SELECT DISTINCT meta_value
FROM {$wpdb->postmeta}
INNER JOIN {$wpdb->posts}
ON {$wpdb->postmeta}.post_id = {$wpdb->posts}.ID
WHERE meta_key = %s
AND post_type = 'review_board'
AND post_status = 'publish'
AND meta_value != ''
ORDER BY meta_value ASC
",
$meta_key
)
);
$clean_values = array();
if ( ! empty( $values ) ) {
foreach ( $values as $value ) {
$value = sanitize_text_field( $value );
if ( ! empty( $value ) ) {
$clean_values[] = $value;
}
}
}
$clean_values = array_unique( $clean_values );
set_transient( $cache_key, $clean_values, HOUR_IN_SECONDS );
return $clean_values;
}
}
if ( ! function_exists( 'rx_review_board_get_current_url' ) ) {
/**
* Current page URL without unsafe input.
*
* @return string
*/
function rx_review_board_get_current_url() {
global $wp;
$current_url = home_url( add_query_arg( array(), $wp->request ) );
return esc_url( $current_url );
}
}
if ( ! function_exists( 'rx_review_board_get_sort_args' ) ) {
/**
* Sorting arguments.
*
* @param string $sort Sort value.
* @return array
*/
function rx_review_board_get_sort_args( $sort ) {
$args = array(
'orderby' => 'title',
'order' => 'ASC',
);
switch ( $sort ) {
case 'name_desc':
$args['orderby'] = 'title';
$args['order'] = 'DESC';
break;
case 'experience_high':
$args['meta_key'] = 'rxrb_experience';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'DESC';
break;
case 'review_count_high':
$args['meta_key'] = 'rxrb_review_count';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'DESC';
break;
case 'recent_reviewed':
$args['meta_key'] = 'rxrb_last_reviewed';
$args['orderby'] = 'meta_value';
$args['order'] = 'DESC';
break;
case 'name_asc':
default:
$args['orderby'] = 'title';
$args['order'] = 'ASC';
break;
}
return $args;
}
}
if ( ! function_exists( 'rx_review_board_get_member_schema' ) ) {
/**
* Person schema for one member.
*
* @param int $post_id Post ID.
* @return array
*/
function rx_review_board_get_member_schema( $post_id ) {
$name = rx_review_board_get_meta( $post_id, 'rxrb_full_name', get_the_title( $post_id ) );
$designation = rx_review_board_get_meta( $post_id, 'rxrb_designation' );
$specialty = rx_review_board_get_meta( $post_id, 'rxrb_specialty' );
$country = rx_review_board_get_meta( $post_id, 'rxrb_country' );
$institution = rx_review_board_get_meta( $post_id, 'rxrb_institution' );
$profile_url = rx_review_board_get_meta( $post_id, 'rxrb_profile_url', get_permalink( $post_id ) );
$image = get_the_post_thumbnail_url( $post_id, 'full' );
$same_as = array();
$orcid = rx_review_board_get_meta( $post_id, 'rxrb_orcid' );
$google = rx_review_board_get_meta( $post_id, 'rxrb_google_scholar' );
$pubmed = rx_review_board_get_meta( $post_id, 'rxrb_pubmed' );
foreach ( array( $orcid, $google, $pubmed ) as $url ) {
if ( ! empty( $url ) && filter_var( $url, FILTER_VALIDATE_URL ) ) {
$same_as[] = esc_url_raw( $url );
}
}
$schema = array(
'@type' => 'Person',
'name' => $name,
'url' => esc_url_raw( $profile_url ),
'jobTitle' => $designation,
'description' => $specialty,
);
if ( $image ) {
$schema['image'] = esc_url_raw( $image );
}
if ( $country ) {
$schema['nationality'] = $country;
}
if ( $institution ) {
$schema['affiliation'] = array(
'@type' => 'Organization',
'name' => $institution,
);
}
if ( ! empty( $same_as ) ) {
$schema['sameAs'] = $same_as;
}
return array_filter( $schema );
}
}
if ( ! function_exists( 'rx_review_board_demo_members' ) ) {
/**
* Fallback members when CPT has no content.
*
* @return array
*/
function rx_review_board_demo_members() {
return array(
array(
'name' => 'Medical Review Board Member',
'designation' => 'Consultant Physician',
'specialty' => 'Internal Medicine',
'country' => 'Global',
'institution' => 'RX Medical Knowledge Network',
'qualification' => 'MBBS, MD',
'experience' => '10+ years',
'bio' => 'This sample profile appears because no review board member has been added yet. Add members using the review_board custom post type or connect this template with your own custom fields.',
'verified' => true,
),
array(
'name' => 'Clinical Content Reviewer',
'designation' => 'Specialist Doctor',
'specialty' => 'Evidence-Based Medicine',
'country' => 'Global',
'institution' => 'RX Health Editorial System',
'qualification' => 'Clinical reviewer',
'experience' => '8+ years',
'bio' => 'This placeholder helps your layout stay beautiful while you are building your real review board database.',
'verified' => true,
),
);
}
}
/**
* ------------------------------------------------------------
* Query Variables
* ------------------------------------------------------------
*/
$paged = max(
1,
get_query_var( 'paged' ) ? absint( get_query_var( 'paged' ) ) : absint( filter_input( INPUT_GET, 'rxrb_page', FILTER_SANITIZE_NUMBER_INT ) )
);
$search_query = isset( $_GET['rxrb_search'] )
? sanitize_text_field( wp_unslash( $_GET['rxrb_search'] ) )
: '';
$specialty_filter = isset( $_GET['rxrb_specialty'] )
? sanitize_text_field( wp_unslash( $_GET['rxrb_specialty'] ) )
: '';
$designation_filter = isset( $_GET['rxrb_designation'] )
? sanitize_text_field( wp_unslash( $_GET['rxrb_designation'] ) )
: '';
$country_filter = isset( $_GET['rxrb_country'] )
? sanitize_text_field( wp_unslash( $_GET['rxrb_country'] ) )
: '';
$status_filter = isset( $_GET['rxrb_status'] )
? sanitize_text_field( wp_unslash( $_GET['rxrb_status'] ) )
: '';
$sort = isset( $_GET['rxrb_sort'] )
? sanitize_key( wp_unslash( $_GET['rxrb_sort'] ) )
: 'name_asc';
$posts_per_page = apply_filters( 'rx_review_board_posts_per_page', 12 );
$meta_query = array(
'relation' => 'AND',
);
if ( ! empty( $specialty_filter ) ) {
$meta_query[] = array(
'key' => 'rxrb_specialty',
'value' => $specialty_filter,
'compare' => '=',
);
}
if ( ! empty( $designation_filter ) ) {
$meta_query[] = array(
'key' => 'rxrb_designation',
'value' => $designation_filter,
'compare' => '=',
);
}
if ( ! empty( $country_filter ) ) {
$meta_query[] = array(
'key' => 'rxrb_country',
'value' => $country_filter,
'compare' => '=',
);
}
if ( 'verified' === $status_filter ) {
$meta_query[] = array(
'key' => 'rxrb_verified',
'value' => array( '1', 'yes', 'true', 'verified' ),
'compare' => 'IN',
);
}
$sort_args = rx_review_board_get_sort_args( $sort );
$query_args = array(
'post_type' => 'review_board',
'post_status' => 'publish',
'posts_per_page' => $posts_per_page,
'paged' => $paged,
's' => $search_query,
'ignore_sticky_posts' => true,
'no_found_rows' => false,
);
if ( count( $meta_query ) > 1 ) {
$query_args['meta_query'] = $meta_query;
}
$query_args = array_merge( $query_args, $sort_args );
$query_args = apply_filters( 'rx_review_board_query_args', $query_args );
$rx_review_board_query = new WP_Query( $query_args );
$specialty_options = rx_review_board_get_field_options( 'rxrb_specialty' );
$designation_options = rx_review_board_get_field_options( 'rxrb_designation' );
$country_options = rx_review_board_get_field_options( 'rxrb_country' );
$schema_members = array();
?>
<main id="primary" class="site-main rx-review-board-page" role="main">
<section class="rxrb-hero" aria-labelledby="rxrb-title">
<div class="rx-container rxrb-hero__inner">
<?php if ( function_exists( 'rx_theme_breadcrumbs' ) ) : ?>
<nav class="rxrb-breadcrumbs" aria-label="<?php esc_attr_e( 'Breadcrumb', 'rx-theme' ); ?>">
<?php rx_theme_breadcrumbs(); ?>
</nav>
<?php endif; ?>
<p class="rxrb-kicker">
<?php esc_html_e( 'RX Health Editorial Governance', 'rx-theme' ); ?>
</p>
<h1 id="rxrb-title" class="rxrb-title">
<?php the_title(); ?>
</h1>
<div class="rxrb-intro">
<?php
while ( have_posts() ) :
the_post();
if ( has_excerpt() ) {
the_excerpt();
} elseif ( get_the_content() ) {
the_content();
} else {
echo '<p>' . esc_html__( 'Our review board supports medical accuracy, clinical clarity, editorial independence, and patient-friendly health education. Every reviewer helps strengthen the quality of RX medical content before it reaches readers.', 'rx-theme' ) . '</p>';
}
endwhile;
?>
</div>
<div class="rxrb-hero__stats" aria-label="<?php esc_attr_e( 'Review board statistics', 'rx-theme' ); ?>">
<div class="rxrb-stat">
<strong><?php echo esc_html( number_format_i18n( (int) $rx_review_board_query->found_posts ) ); ?></strong>
<span><?php esc_html_e( 'Listed reviewers', 'rx-theme' ); ?></span>
</div>
<div class="rxrb-stat">
<strong><?php echo esc_html( number_format_i18n( count( $specialty_options ) ) ); ?></strong>
<span><?php esc_html_e( 'Medical specialties', 'rx-theme' ); ?></span>
</div>
<div class="rxrb-stat">
<strong><?php echo esc_html( number_format_i18n( count( $country_options ) ) ); ?></strong>
<span><?php esc_html_e( 'Countries represented', 'rx-theme' ); ?></span>
</div>
</div>
</div>
</section>
<section class="rxrb-governance" aria-labelledby="rxrb-governance-title">
<div class="rx-container">
<h2 id="rxrb-governance-title" class="rxrb-section-title">
<?php esc_html_e( 'How the RX Review Board Helps Readers', 'rx-theme' ); ?>
</h2>
<div class="rxrb-governance-grid">
<article class="rxrb-governance-card">
<h3><?php esc_html_e( 'Medical Accuracy', 'rx-theme' ); ?></h3>
<p><?php esc_html_e( 'Reviewers check important medical statements, disease explanations, diagnostic concepts, treatment language, and safety warnings so readers receive dependable health information.', 'rx-theme' ); ?></p>
</article>
<article class="rxrb-governance-card">
<h3><?php esc_html_e( 'Evidence-Based Editing', 'rx-theme' ); ?></h3>
<p><?php esc_html_e( 'The review process encourages use of reliable clinical references, current medical understanding, clear definitions, and balanced explanations without unnecessary fear or confusion.', 'rx-theme' ); ?></p>
</article>
<article class="rxrb-governance-card">
<h3><?php esc_html_e( 'Plain English Health Education', 'rx-theme' ); ?></h3>
<p><?php esc_html_e( 'Complex medical terms are translated into simple, readable language so patients, families, students, and general readers can understand the topic more easily.', 'rx-theme' ); ?></p>
</article>
<article class="rxrb-governance-card">
<h3><?php esc_html_e( 'Editorial Independence', 'rx-theme' ); ?></h3>
<p><?php esc_html_e( 'Review board members help protect the content from unsupported claims, promotional pressure, unsafe advice, and unclear medical recommendations.', 'rx-theme' ); ?></p>
</article>
</div>
</div>
</section>
<section class="rxrb-filter-section" aria-labelledby="rxrb-filter-title">
<div class="rx-container">
<h2 id="rxrb-filter-title" class="screen-reader-text">
<?php esc_html_e( 'Search and filter review board members', 'rx-theme' ); ?>
</h2>
<form class="rxrb-filter-form" method="get" action="<?php echo esc_url( get_permalink() ); ?>">
<div class="rxrb-filter-grid">
<div class="rxrb-field">
<label for="rxrb_search">
<?php esc_html_e( 'Search by name or keyword', 'rx-theme' ); ?>
</label>
<input
type="search"
id="rxrb_search"
name="rxrb_search"
value="<?php echo esc_attr( $search_query ); ?>"
placeholder="<?php esc_attr_e( 'Example: cardiology, surgeon, professor', 'rx-theme' ); ?>"
/>
</div>
<div class="rxrb-field">
<label for="rxrb_specialty">
<?php esc_html_e( 'Specialty', 'rx-theme' ); ?>
</label>
<select id="rxrb_specialty" name="rxrb_specialty">
<option value=""><?php esc_html_e( 'All specialties', 'rx-theme' ); ?></option>
<?php foreach ( $specialty_options as $option ) : ?>
<option value="<?php echo esc_attr( $option ); ?>" <?php selected( $specialty_filter, $option ); ?>>
<?php echo esc_html( $option ); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="rxrb-field">
<label for="rxrb_designation">
<?php esc_html_e( 'Designation', 'rx-theme' ); ?>
</label>
<select id="rxrb_designation" name="rxrb_designation">
<option value=""><?php esc_html_e( 'All designations', 'rx-theme' ); ?></option>
<?php foreach ( $designation_options as $option ) : ?>
<option value="<?php echo esc_attr( $option ); ?>" <?php selected( $designation_filter, $option ); ?>>
<?php echo esc_html( $option ); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="rxrb-field">
<label for="rxrb_country">
<?php esc_html_e( 'Country', 'rx-theme' ); ?>
</label>
<select id="rxrb_country" name="rxrb_country">
<option value=""><?php esc_html_e( 'All countries', 'rx-theme' ); ?></option>
<?php foreach ( $country_options as $option ) : ?>
<option value="<?php echo esc_attr( $option ); ?>" <?php selected( $country_filter, $option ); ?>>
<?php echo esc_html( $option ); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="rxrb-field">
<label for="rxrb_status">
<?php esc_html_e( 'Status', 'rx-theme' ); ?>
</label>
<select id="rxrb_status" name="rxrb_status">
<option value=""><?php esc_html_e( 'All members', 'rx-theme' ); ?></option>
<option value="verified" <?php selected( $status_filter, 'verified' ); ?>>
<?php esc_html_e( 'Verified only', 'rx-theme' ); ?>
</option>
</select>
</div>
<div class="rxrb-field">
<label for="rxrb_sort">
<?php esc_html_e( 'Sort by', 'rx-theme' ); ?>
</label>
<select id="rxrb_sort" name="rxrb_sort">
<option value="name_asc" <?php selected( $sort, 'name_asc' ); ?>>
<?php esc_html_e( 'Name A to Z', 'rx-theme' ); ?>
</option>
<option value="name_desc" <?php selected( $sort, 'name_desc' ); ?>>
<?php esc_html_e( 'Name Z to A', 'rx-theme' ); ?>
</option>
<option value="experience_high" <?php selected( $sort, 'experience_high' ); ?>>
<?php esc_html_e( 'Highest experience', 'rx-theme' ); ?>
</option>
<option value="review_count_high" <?php selected( $sort, 'review_count_high' ); ?>>
<?php esc_html_e( 'Most reviewed articles', 'rx-theme' ); ?>
</option>
<option value="recent_reviewed" <?php selected( $sort, 'recent_reviewed' ); ?>>
<?php esc_html_e( 'Recently reviewed', 'rx-theme' ); ?>
</option>
</select>
</div>
</div>
<div class="rxrb-filter-actions">
<button type="submit" class="rxrb-button rxrb-button--primary">
<?php esc_html_e( 'Apply Filters', 'rx-theme' ); ?>
</button>
<a class="rxrb-button rxrb-button--secondary" href="<?php echo esc_url( get_permalink() ); ?>">
<?php esc_html_e( 'Reset', 'rx-theme' ); ?>
</a>
</div>
</form>
</div>
</section>
<section class="rxrb-members-section" aria-labelledby="rxrb-members-title">
<div class="rx-container">
<div class="rxrb-section-heading">
<h2 id="rxrb-members-title" class="rxrb-section-title">
<?php esc_html_e( 'Meet the Review Board', 'rx-theme' ); ?>
</h2>
<p class="rxrb-results-count">
<?php
printf(
esc_html(
_n(
'%s reviewer found',
'%s reviewers found',
(int) $rx_review_board_query->found_posts,
'rx-theme'
)
),
esc_html( number_format_i18n( (int) $rx_review_board_query->found_posts ) )
);
?>
</p>
</div>
<?php if ( $rx_review_board_query->have_posts() ) : ?>
<div class="rxrb-members-grid">
<?php
while ( $rx_review_board_query->have_posts() ) :
$rx_review_board_query->the_post();
$member_id = get_the_ID();
$name = rx_review_board_get_meta( $member_id, 'rxrb_full_name', get_the_title() );
$designation = rx_review_board_get_meta( $member_id, 'rxrb_designation', __( 'Medical Reviewer', 'rx-theme' ) );
$specialty = rx_review_board_get_meta( $member_id, 'rxrb_specialty', __( 'General Medicine', 'rx-theme' ) );
$country = rx_review_board_get_meta( $member_id, 'rxrb_country' );
$institution = rx_review_board_get_meta( $member_id, 'rxrb_institution' );
$qualification = rx_review_board_get_meta( $member_id, 'rxrb_qualification' );
$experience = rx_review_board_get_meta( $member_id, 'rxrb_experience' );
$profile_url = rx_review_board_get_meta( $member_id, 'rxrb_profile_url', get_permalink() );
$orcid = rx_review_board_get_meta( $member_id, 'rxrb_orcid' );
$google = rx_review_board_get_meta( $member_id, 'rxrb_google_scholar' );
$pubmed = rx_review_board_get_meta( $member_id, 'rxrb_pubmed' );
$verified = rx_review_board_bool_meta( $member_id, 'rxrb_verified' );
$review_count = rx_review_board_get_meta( $member_id, 'rxrb_review_count', '0' );
$last_reviewed = rx_review_board_get_meta( $member_id, 'rxrb_last_reviewed' );
$short_bio = rx_review_board_get_meta( $member_id, 'rxrb_short_bio' );
if ( empty( $short_bio ) ) {
$short_bio = wp_trim_words( wp_strip_all_tags( get_the_excerpt() ), 28, '...' );
}
$schema_members[] = rx_review_board_get_member_schema( $member_id );
?>
<article id="reviewer-<?php echo esc_attr( $member_id ); ?>" <?php post_class( 'rxrb-member-card' ); ?>>
<div class="rxrb-member-card__media">
<a href="<?php echo esc_url( $profile_url ); ?>" aria-label="<?php echo esc_attr( sprintf( __( 'View profile of %s', 'rx-theme' ), $name ) ); ?>">
<?php if ( has_post_thumbnail() ) : ?>
<?php
the_post_thumbnail(
'medium_large',
array(
'class' => 'rxrb-member-card__image',
'loading' => 'lazy',
'alt' => esc_attr( $name ),
)
);
?>
<?php else : ?>
<div class="rxrb-member-card__avatar" aria-hidden="true">
<?php echo esc_html( mb_substr( $name, 0, 1 ) ); ?>
</div>
<?php endif; ?>
</a>
<?php if ( $verified ) : ?>
<span class="rxrb-badge rxrb-badge--verified">
<?php esc_html_e( 'Verified', 'rx-theme' ); ?>
</span>
<?php endif; ?>
</div>
<div class="rxrb-member-card__body">
<h3 class="rxrb-member-card__name">
<a href="<?php echo esc_url( $profile_url ); ?>">
<?php echo esc_html( $name ); ?>
</a>
</h3>
<p class="rxrb-member-card__designation">
<?php echo esc_html( $designation ); ?>
</p>
<p class="rxrb-member-card__specialty">
<?php echo esc_html( $specialty ); ?>
</p>
<?php if ( ! empty( $qualification ) ) : ?>
<p class="rxrb-member-card__qualification">
<strong><?php esc_html_e( 'Qualification:', 'rx-theme' ); ?></strong>
<?php echo esc_html( $qualification ); ?>
</p>
<?php endif; ?>
<?php if ( ! empty( $institution ) ) : ?>
<p class="rxrb-member-card__institution">
<strong><?php esc_html_e( 'Institution:', 'rx-theme' ); ?></strong>
<?php echo esc_html( $institution ); ?>
</p>
<?php endif; ?>
<?php if ( ! empty( $country ) ) : ?>
<p class="rxrb-member-card__country">
<strong><?php esc_html_e( 'Country:', 'rx-theme' ); ?></strong>
<?php echo esc_html( $country ); ?>
</p>
<?php endif; ?>
<?php if ( ! empty( $experience ) ) : ?>
<p class="rxrb-member-card__experience">
<strong><?php esc_html_e( 'Experience:', 'rx-theme' ); ?></strong>
<?php echo esc_html( $experience ); ?>
<?php esc_html_e( 'years', 'rx-theme' ); ?>
</p>
<?php endif; ?>
<?php if ( ! empty( $short_bio ) ) : ?>
<p class="rxrb-member-card__bio">
<?php echo esc_html( $short_bio ); ?>
</p>
<?php endif; ?>
<div class="rxrb-member-card__meta">
<span>
<?php
printf(
esc_html__( '%s articles reviewed', 'rx-theme' ),
esc_html( number_format_i18n( (int) $review_count ) )
);
?>
</span>
<?php if ( ! empty( $last_reviewed ) ) : ?>
<span>
<?php
printf(
esc_html__( 'Last reviewed: %s', 'rx-theme' ),
esc_html( date_i18n( get_option( 'date_format' ), strtotime( $last_reviewed ) ) )
);
?>
</span>
<?php endif; ?>
</div>
<div class="rxrb-member-card__links">
<a class="rxrb-profile-link" href="<?php echo esc_url( $profile_url ); ?>">
<?php esc_html_e( 'View Profile', 'rx-theme' ); ?>
</a>
<?php if ( ! empty( $orcid ) && filter_var( $orcid, FILTER_VALIDATE_URL ) ) : ?>
<a href="<?php echo esc_url( $orcid ); ?>" rel="nofollow noopener" target="_blank">
<?php esc_html_e( 'ORCID', 'rx-theme' ); ?>
</a>
<?php endif; ?>
<?php if ( ! empty( $google ) && filter_var( $google, FILTER_VALIDATE_URL ) ) : ?>
<a href="<?php echo esc_url( $google ); ?>" rel="nofollow noopener" target="_blank">
<?php esc_html_e( 'Scholar', 'rx-theme' ); ?>
</a>
<?php endif; ?>
<?php if ( ! empty( $pubmed ) && filter_var( $pubmed, FILTER_VALIDATE_URL ) ) : ?>
<a href="<?php echo esc_url( $pubmed ); ?>" rel="nofollow noopener" target="_blank">
<?php esc_html_e( 'PubMed', 'rx-theme' ); ?>
</a>
<?php endif; ?>
</div>
</div>
</article>
<?php endwhile; ?>
</div>
<?php
$pagination_links = paginate_links(
array(
'total' => max( 1, (int) $rx_review_board_query->max_num_pages ),
'current' => $paged,
'mid_size' => 2,
'prev_text' => esc_html__( 'Previous', 'rx-theme' ),
'next_text' => esc_html__( 'Next', 'rx-theme' ),
'type' => 'list',
'add_args' => array_filter(
array(
'rxrb_search' => $search_query,
'rxrb_specialty' => $specialty_filter,
'rxrb_designation' => $designation_filter,
'rxrb_country' => $country_filter,
'rxrb_status' => $status_filter,
'rxrb_sort' => $sort,
)
),
)
);
?>
<?php if ( $pagination_links ) : ?>
<nav class="rxrb-pagination" aria-label="<?php esc_attr_e( 'Review board pagination', 'rx-theme' ); ?>">
<?php echo wp_kses_post( $pagination_links ); ?>
</nav>
<?php endif; ?>
<?php else : ?>
<?php $demo_members = rx_review_board_demo_members(); ?>
<div class="rxrb-empty">
<h3><?php esc_html_e( 'No review board members found yet', 'rx-theme' ); ?></h3>
<p><?php esc_html_e( 'You can add real members by creating a review_board custom post type and adding the supported custom fields. Until then, these sample cards show how the final design will look.', 'rx-theme' ); ?></p>
</div>
<div class="rxrb-members-grid rxrb-members-grid--demo">
<?php foreach ( $demo_members as $demo ) : ?>
<article class="rxrb-member-card rxrb-member-card--demo">
<div class="rxrb-member-card__media">
<div class="rxrb-member-card__avatar" aria-hidden="true">
<?php echo esc_html( mb_substr( $demo['name'], 0, 1 ) ); ?>
</div>
<?php if ( ! empty( $demo['verified'] ) ) : ?>
<span class="rxrb-badge rxrb-badge--verified">
<?php esc_html_e( 'Verified', 'rx-theme' ); ?>
</span>
<?php endif; ?>
</div>
<div class="rxrb-member-card__body">
<h3 class="rxrb-member-card__name">
<?php echo esc_html( $demo['name'] ); ?>
</h3>
<p class="rxrb-member-card__designation">
<?php echo esc_html( $demo['designation'] ); ?>
</p>
<p class="rxrb-member-card__specialty">
<?php echo esc_html( $demo['specialty'] ); ?>
</p>
<p>
<strong><?php esc_html_e( 'Qualification:', 'rx-theme' ); ?></strong>
<?php echo esc_html( $demo['qualification'] ); ?>
</p>
<p>
<strong><?php esc_html_e( 'Institution:', 'rx-theme' ); ?></strong>
<?php echo esc_html( $demo['institution'] ); ?>
</p>
<p class="rxrb-member-card__bio">
<?php echo esc_html( $demo['bio'] ); ?>
</p>
</div>
</article>
<?php endforeach; ?>
</div>
<?php endif; ?>
<?php wp_reset_postdata(); ?>
</div>
</section>
<section class="rxrb-editorial-process" aria-labelledby="rxrb-process-title">
<div class="rx-container">
<h2 id="rxrb-process-title" class="rxrb-section-title">
<?php esc_html_e( 'RX Medical Review Process', 'rx-theme' ); ?>
</h2>
<div class="rxrb-process-list">
<article class="rxrb-process-item">
<span class="rxrb-process-number">01</span>
<h3><?php esc_html_e( 'Topic Selection', 'rx-theme' ); ?></h3>
<p><?php esc_html_e( 'Medical topics are selected based on patient need, public health relevance, search demand, clinical importance, and educational value.', 'rx-theme' ); ?></p>
</article>
<article class="rxrb-process-item">
<span class="rxrb-process-number">02</span>
<h3><?php esc_html_e( 'Evidence Review', 'rx-theme' ); ?></h3>
<p><?php esc_html_e( 'Writers and reviewers examine trusted clinical information, diagnostic standards, medical terminology, and treatment principles before publication.', 'rx-theme' ); ?></p>
</article>
<article class="rxrb-process-item">
<span class="rxrb-process-number">03</span>
<h3><?php esc_html_e( 'Clinical Review', 'rx-theme' ); ?></h3>
<p><?php esc_html_e( 'Reviewers check whether the article explains the condition correctly, avoids unsafe claims, and uses language suitable for general readers.', 'rx-theme' ); ?></p>
</article>
<article class="rxrb-process-item">
<span class="rxrb-process-number">04</span>
<h3><?php esc_html_e( 'Update Cycle', 'rx-theme' ); ?></h3>
<p><?php esc_html_e( 'Content should be reviewed again when medical guidelines, evidence, drug safety information, or diagnostic recommendations change.', 'rx-theme' ); ?></p>
</article>
</div>
</div>
</section>
</main>
<?php
/**
* ------------------------------------------------------------
* JSON-LD Schema
* ------------------------------------------------------------
*/
$schema = array(
'@context' => 'https://schema.org',
'@type' => 'WebPage',
'name' => get_the_title(),
'url' => get_permalink(),
'description' => wp_strip_all_tags( get_the_excerpt() ),
'publisher' => array(
'@type' => 'Organization',
'name' => get_bloginfo( 'name' ),
'url' => home_url( '/' ),
),
'mainEntity' => array(
'@type' => 'ItemList',
'name' => __( 'RX Review Board Members', 'rx-theme' ),
'numberOfItems' => count( $schema_members ),
'itemListElement' => array(),
),
);
if ( ! empty( $schema_members ) ) {
foreach ( $schema_members as $index => $member_schema ) {
$schema['mainEntity']['itemListElement'][] = array(
'@type' => 'ListItem',
'position' => $index + 1,
'item' => $member_schema,
);
}
}
?>
<script type="application/ld+json">
<?php echo wp_json_encode( $schema, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT ); ?>
</script>
<?php
get_footer();
Add this CSS in:
assets/css/templates/review-board.css
.rx-review-board-page {
--rxrb-bg: var(--rx-color-background, #ffffff);
--rxrb-soft-bg: var(--rx-color-surface, #f7f9fc);
--rxrb-card-bg: var(--rx-color-card, #ffffff);
--rxrb-text: var(--rx-color-text, #162033);
--rxrb-muted: var(--rx-color-muted, #667085);
--rxrb-border: var(--rx-color-border, #e5e7eb);
--rxrb-primary: var(--rx-color-primary, #1266f1);
--rxrb-primary-dark: var(--rx-color-primary-dark, #084ab8);
--rxrb-success: var(--rx-color-success, #11845b);
--rxrb-radius: var(--rx-radius-lg, 18px);
--rxrb-shadow: 0 18px 45px rgba(16, 24, 40, 0.08);
color: var(--rxrb-text);
background: var(--rxrb-bg);
}
.rx-container {
width: min(1180px, calc(100% - 32px));
margin-inline: auto;
}
.rxrb-hero {
padding: clamp(48px, 7vw, 96px) 0;
background:
radial-gradient(circle at top left, rgba(18, 102, 241, 0.12), transparent 36%),
linear-gradient(135deg, #f8fbff 0%, #ffffff 60%);
}
.rxrb-kicker {
margin: 0 0 12px;
color: var(--rxrb-primary);
font-weight: 700;
text-transform: uppercase;
letter-spacing: 0.08em;
font-size: 0.82rem;
}
.rxrb-title {
margin: 0;
font-size: clamp(2.2rem, 5vw, 4.7rem);
line-height: 1.04;
letter-spacing: -0.045em;
}
.rxrb-intro {
max-width: 780px;
margin-top: 22px;
color: var(--rxrb-muted);
font-size: clamp(1rem, 2vw, 1.18rem);
line-height: 1.75;
}
.rxrb-hero__stats {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 18px;
margin-top: 34px;
max-width: 820px;
}
.rxrb-stat {
padding: 22px;
background: rgba(255, 255, 255, 0.78);
border: 1px solid var(--rxrb-border);
border-radius: var(--rxrb-radius);
box-shadow: 0 12px 30px rgba(16, 24, 40, 0.06);
backdrop-filter: blur(10px);
}
.rxrb-stat strong {
display: block;
font-size: clamp(1.7rem, 3vw, 2.5rem);
line-height: 1;
color: var(--rxrb-primary);
}
.rxrb-stat span {
display: block;
margin-top: 8px;
color: var(--rxrb-muted);
font-size: 0.95rem;
}
.rxrb-governance,
.rxrb-filter-section,
.rxrb-members-section,
.rxrb-editorial-process {
padding: clamp(42px, 6vw, 76px) 0;
}
.rxrb-governance,
.rxrb-editorial-process {
background: var(--rxrb-soft-bg);
}
.rxrb-section-heading {
display: flex;
align-items: end;
justify-content: space-between;
gap: 20px;
margin-bottom: 28px;
}
.rxrb-section-title {
margin: 0 0 26px;
font-size: clamp(1.75rem, 3vw, 2.65rem);
line-height: 1.12;
letter-spacing: -0.025em;
}
.rxrb-results-count {
margin: 0 0 30px;
color: var(--rxrb-muted);
}
.rxrb-governance-grid,
.rxrb-process-list {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 18px;
}
.rxrb-governance-card,
.rxrb-process-item {
padding: 24px;
background: var(--rxrb-card-bg);
border: 1px solid var(--rxrb-border);
border-radius: var(--rxrb-radius);
box-shadow: 0 10px 24px rgba(16, 24, 40, 0.04);
}
.rxrb-governance-card h3,
.rxrb-process-item h3 {
margin: 0 0 10px;
font-size: 1.08rem;
}
.rxrb-governance-card p,
.rxrb-process-item p {
margin: 0;
color: var(--rxrb-muted);
line-height: 1.7;
}
.rxrb-process-number {
display: inline-flex;
align-items: center;
justify-content: center;
width: 42px;
height: 42px;
margin-bottom: 16px;
border-radius: 999px;
background: rgba(18, 102, 241, 0.1);
color: var(--rxrb-primary);
font-weight: 800;
}
.rxrb-filter-form {
padding: 22px;
background: var(--rxrb-card-bg);
border: 1px solid var(--rxrb-border);
border-radius: var(--rxrb-radius);
box-shadow: var(--rxrb-shadow);
}
.rxrb-filter-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 16px;
}
.rxrb-field label {
display: block;
margin-bottom: 8px;
font-weight: 700;
font-size: 0.92rem;
}
.rxrb-field input,
.rxrb-field select {
width: 100%;
min-height: 48px;
padding: 10px 14px;
border: 1px solid var(--rxrb-border);
border-radius: 12px;
background: #fff;
color: var(--rxrb-text);
font: inherit;
}
.rxrb-field input:focus,
.rxrb-field select:focus {
outline: 3px solid rgba(18, 102, 241, 0.18);
border-color: var(--rxrb-primary);
}
.rxrb-filter-actions {
display: flex;
flex-wrap: wrap;
gap: 12px;
margin-top: 18px;
}
.rxrb-button {
display: inline-flex;
align-items: center;
justify-content: center;
min-height: 46px;
padding: 10px 18px;
border-radius: 12px;
border: 1px solid transparent;
font-weight: 700;
text-decoration: none;
cursor: pointer;
}
.rxrb-button--primary {
background: var(--rxrb-primary);
color: #fff;
}
.rxrb-button--primary:hover {
background: var(--rxrb-primary-dark);
color: #fff;
}
.rxrb-button--secondary {
background: #fff;
color: var(--rxrb-text);
border-color: var(--rxrb-border);
}
.rxrb-members-grid {
display: grid;
grid-template-columns: repeat(3, minmax(0, 1fr));
gap: 22px;
}
.rxrb-member-card {
position: relative;
overflow: hidden;
background: var(--rxrb-card-bg);
border: 1px solid var(--rxrb-border);
border-radius: var(--rxrb-radius);
box-shadow: 0 14px 32px rgba(16, 24, 40, 0.06);
transition: transform 180ms ease, box-shadow 180ms ease, border-color 180ms ease;
}
.rxrb-member-card:hover {
transform: translateY(-4px);
border-color: rgba(18, 102, 241, 0.25);
box-shadow: var(--rxrb-shadow);
}
.rxrb-member-card__media {
position: relative;
aspect-ratio: 16 / 10;
background: linear-gradient(135deg, rgba(18, 102, 241, 0.12), rgba(17, 132, 91, 0.12));
display: flex;
align-items: center;
justify-content: center;
}
.rxrb-member-card__image {
width: 100%;
height: 100%;
object-fit: cover;
display: block;
}
.rxrb-member-card__avatar {
width: 96px;
height: 96px;
border-radius: 999px;
display: inline-flex;
align-items: center;
justify-content: center;
background: #fff;
color: var(--rxrb-primary);
font-size: 2.8rem;
font-weight: 800;
box-shadow: 0 12px 34px rgba(16, 24, 40, 0.12);
}
.rxrb-badge {
position: absolute;
top: 14px;
right: 14px;
display: inline-flex;
align-items: center;
min-height: 30px;
padding: 6px 10px;
border-radius: 999px;
font-size: 0.78rem;
font-weight: 800;
}
.rxrb-badge--verified {
background: rgba(17, 132, 91, 0.12);
color: var(--rxrb-success);
border: 1px solid rgba(17, 132, 91, 0.22);
}
.rxrb-member-card__body {
padding: 22px;
}
.rxrb-member-card__name {
margin: 0 0 6px;
font-size: 1.28rem;
line-height: 1.25;
}
.rxrb-member-card__name a {
color: inherit;
text-decoration: none;
}
.rxrb-member-card__name a:hover {
color: var(--rxrb-primary);
}
.rxrb-member-card__designation {
margin: 0;
color: var(--rxrb-primary);
font-weight: 700;
}
.rxrb-member-card__specialty {
margin: 8px 0 14px;
color: var(--rxrb-muted);
font-weight: 600;
}
.rxrb-member-card__body p {
line-height: 1.65;
}
.rxrb-member-card__qualification,
.rxrb-member-card__institution,
.rxrb-member-card__country,
.rxrb-member-card__experience {
margin: 8px 0;
color: var(--rxrb-text);
font-size: 0.95rem;
}
.rxrb-member-card__bio {
margin-top: 14px;
color: var(--rxrb-muted);
}
.rxrb-member-card__meta {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin-top: 16px;
color: var(--rxrb-muted);
font-size: 0.86rem;
}
.rxrb-member-card__meta span {
padding: 6px 9px;
border-radius: 999px;
background: var(--rxrb-soft-bg);
}
.rxrb-member-card__links {
display: flex;
flex-wrap: wrap;
gap: 10px;
margin-top: 18px;
}
.rxrb-member-card__links a {
display: inline-flex;
align-items: center;
min-height: 34px;
padding: 6px 10px;
border-radius: 999px;
background: var(--rxrb-soft-bg);
color: var(--rxrb-primary);
text-decoration: none;
font-weight: 700;
font-size: 0.9rem;
}
.rxrb-member-card__links a:hover {
background: var(--rxrb-primary);
color: #fff;
}
.rxrb-empty {
padding: 28px;
margin-bottom: 24px;
border: 1px dashed var(--rxrb-border);
border-radius: var(--rxrb-radius);
background: var(--rxrb-soft-bg);
}
.rxrb-empty h3 {
margin-top: 0;
}
.rxrb-empty p {
margin-bottom: 0;
color: var(--rxrb-muted);
}
.rxrb-pagination {
margin-top: 36px;
}
.rxrb-pagination ul {
display: flex;
flex-wrap: wrap;
gap: 8px;
list-style: none;
padding: 0;
margin: 0;
}
.rxrb-pagination a,
.rxrb-pagination span {
display: inline-flex;
align-items: center;
justify-content: center;
min-width: 42px;
min-height: 42px;
padding: 8px 12px;
border-radius: 12px;
border: 1px solid var(--rxrb-border);
text-decoration: none;
color: var(--rxrb-text);
background: #fff;
font-weight: 700;
}
.rxrb-pagination .current {
background: var(--rxrb-primary);
color: #fff;
border-color: var(--rxrb-primary);
}
.screen-reader-text {
position: absolute;
width: 1px;
height: 1px;
padding: 0;
margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap;
border: 0;
}
@media (max-width: 1024px) {
.rxrb-governance-grid,
.rxrb-process-list {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.rxrb-members-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
.rxrb-filter-grid {
grid-template-columns: repeat(2, minmax(0, 1fr));
}
}
@media (max-width: 700px) {
.rxrb-hero__stats,
.rxrb-governance-grid,
.rxrb-process-list,
.rxrb-members-grid,
.rxrb-filter-grid {
grid-template-columns: 1fr;
}
.rxrb-section-heading {
display: block;
}
.rxrb-title {
font-size: 2.4rem;
}
.rxrb-filter-actions {
display: grid;
}
.rxrb-button {
width: 100%;
}
}
To load this CSS only on the Review Board page, add this in your functions.php or inc/core/enqueue.php:
/**
* Enqueue Review Board template CSS.
*/
function rx_theme_enqueue_review_board_template_assets() {
if ( is_page_template( 'templates/template-review-board.php' ) ) {
wp_enqueue_style(
'rx-review-board-template',
get_template_directory_uri() . '/assets/css/templates/review-board.css',
array(),
wp_get_theme()->get( 'Version' )
);
}
}
add_action( 'wp_enqueue_scripts', 'rx_theme_enqueue_review_board_template_assets' );
Important: this template is ready for a future review_board custom post type. If you have not created the CPT yet, the page will still show a beautiful fallback demo section instead of breaking.