add client rest api
This commit is contained in:
@@ -1,275 +1,257 @@
|
||||
---
|
||||
import { getLatestAnews } from '../lib/api/posts.js';
|
||||
import { fetchWPRestGet } from "@/lib/api/wp-rest-get-client";
|
||||
|
||||
// Функции для работы с датами
|
||||
|
||||
// Даты/время
|
||||
function formatDate(dateString: string): string {
|
||||
const date = new Date(dateString);
|
||||
const today = new Date();
|
||||
const yesterday = new Date(today);
|
||||
yesterday.setDate(yesterday.getDate() - 1);
|
||||
|
||||
if (date.toDateString() === today.toDateString()) {
|
||||
return 'Сегодня';
|
||||
}
|
||||
if (date.toDateString() === today.toDateString()) return 'Сегодня';
|
||||
if (date.toDateString() === yesterday.toDateString()) return 'Вчера';
|
||||
|
||||
if (date.toDateString() === yesterday.toDateString()) {
|
||||
return 'Вчера';
|
||||
}
|
||||
|
||||
return date.toLocaleDateString('ru-RU', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric'
|
||||
});
|
||||
return date.toLocaleDateString('ru-RU', { day: 'numeric', month: 'long', year: 'numeric' });
|
||||
}
|
||||
|
||||
function formatTime(dateString: string): string {
|
||||
const date = new Date(dateString);
|
||||
return date.toLocaleTimeString('ru-RU', {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit'
|
||||
});
|
||||
return date.toLocaleTimeString('ru-RU', { hour: '2-digit', minute: '2-digit' });
|
||||
}
|
||||
|
||||
function groupByDate(posts: Array<{ date: string }>) {
|
||||
const grouped: Record<string, Array<any>> = {};
|
||||
|
||||
posts.forEach(post => {
|
||||
const date = new Date(post.date);
|
||||
const dateKey = date.toISOString().split('T')[0];
|
||||
|
||||
if (!grouped[dateKey]) {
|
||||
grouped[dateKey] = [];
|
||||
}
|
||||
|
||||
grouped[dateKey].push(post);
|
||||
posts.forEach((post) => {
|
||||
const d = new Date(post.date);
|
||||
const key = d.toISOString().split('T')[0];
|
||||
(grouped[key] ??= []).push(post);
|
||||
});
|
||||
|
||||
const sortedEntries = Object.entries(grouped).sort((a, b) =>
|
||||
b[0].localeCompare(a[0])
|
||||
);
|
||||
|
||||
return Object.fromEntries(sortedEntries);
|
||||
return Object.fromEntries(Object.entries(grouped).sort((a, b) => b[0].localeCompare(a[0])));
|
||||
}
|
||||
|
||||
// Получаем данные при сборке (используем правильное имя функции)
|
||||
const posts = await getLatestAnews(20);
|
||||
const groupedPosts = groupByDate(posts);
|
||||
const totalPosts = posts.length;
|
||||
// Новости
|
||||
const newsPosts = await getLatestAnews(20);
|
||||
const groupedNews = groupByDate(newsPosts);
|
||||
|
||||
// Топ-10
|
||||
type TopItem = { uri?: string; link?: string; title: string; date: string };
|
||||
type ApiResp = { top?: { items?: TopItem[] } };
|
||||
|
||||
let topPosts: TopItem[] = [];
|
||||
try {
|
||||
const data = await fetchWPRestGet<ApiResp>("my/v1/news-top", { per_page: 20 });
|
||||
topPosts = (data?.top?.items ?? []).slice(0, 10);
|
||||
} catch {
|
||||
topPosts = [];
|
||||
}
|
||||
|
||||
const hasNews = newsPosts.length > 0;
|
||||
const hasTop = topPosts.length > 0;
|
||||
|
||||
// По умолчанию открываем вкладку, где есть данные
|
||||
const defaultTab: "news" | "top" = hasTop ? "top" : "news";
|
||||
---
|
||||
|
||||
<!-- HTML разметка -->
|
||||
<div class="endnews-container">
|
||||
<!-- Шапка с заголовком и счетчиком -->
|
||||
<div class="endnews-header">
|
||||
<h4 class="endnews-title">Новости</h4>
|
||||
</div>
|
||||
{(hasNews || hasTop) && (
|
||||
<div class="endnews-container">
|
||||
<div class="endnews-header">
|
||||
<h4 class="endnews-title">Новости</h4>
|
||||
</div>
|
||||
|
||||
<!-- Список новостей с группировкой по датам -->
|
||||
<div class="latestnews-list">
|
||||
{Object.entries(groupedPosts).map(([dateKey, datePosts]) => {
|
||||
const dateStr = new Date(dateKey).toLocaleDateString('ru-RU', {
|
||||
day: 'numeric',
|
||||
month: 'long',
|
||||
year: 'numeric'
|
||||
});
|
||||
{/* Radio-кнопки ВНЕ .endnews-tabs для работы CSS-селекторов */}
|
||||
<input
|
||||
class="endnews-tab-input"
|
||||
type="radio"
|
||||
name="endnews-tab"
|
||||
id="endnews-tab-news"
|
||||
checked={defaultTab === "news"}
|
||||
/>
|
||||
<input
|
||||
class="endnews-tab-input"
|
||||
type="radio"
|
||||
name="endnews-tab"
|
||||
id="endnews-tab-top"
|
||||
checked={defaultTab === "top"}
|
||||
/>
|
||||
|
||||
return (
|
||||
<div class="latestnews-date-group" key={dateKey}>
|
||||
{/* Только labels в блоке табов */}
|
||||
<div class="endnews-tabs">
|
||||
<label class="endnews-tab-label" for="endnews-tab-news">Новости</label>
|
||||
<label class="endnews-tab-label" for="endnews-tab-top">Топ‑10</label>
|
||||
</div>
|
||||
|
||||
{/* Контент: две панели, показываем нужную через :checked */}
|
||||
<div class="latestnews-list">
|
||||
<section class="endnews-panel endnews-panel--news" aria-label="Новости">
|
||||
{Object.entries(groupedNews).map(([dateKey, datePosts]) => (
|
||||
<div class="latestnews-date-group" key={dateKey}>
|
||||
<div class="latestnews-date">{formatDate(dateKey + 'T00:00:00')}</div>
|
||||
|
||||
|
||||
<!-- Список новостей за эту дату -->
|
||||
{datePosts.map((post, index) => {
|
||||
const postNumber = index + 1;
|
||||
const isLastInGroup = postNumber === datePosts.length;
|
||||
|
||||
return (
|
||||
{datePosts.map((post) => (
|
||||
<article class="lastnews-item" key={post.uri}>
|
||||
|
||||
<div class="lastnews-time">
|
||||
{formatTime(post.date)}
|
||||
</div>
|
||||
|
||||
<!-- Заголовок новости -->
|
||||
<div class="lastnews-time">{formatTime(post.date)}</div>
|
||||
<div class="lastnews-content">
|
||||
<a
|
||||
href={post.uri || '#'}
|
||||
class="endnews-link"
|
||||
>
|
||||
{post.title}
|
||||
</a>
|
||||
<a href={post.uri || '#'} class="endnews-link">
|
||||
{post.title}
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
</article>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
))}
|
||||
</div>
|
||||
))}
|
||||
</section>
|
||||
|
||||
<section class="endnews-panel endnews-panel--top" aria-label="Топ-10">
|
||||
{topPosts.map((post, i) => (
|
||||
<article class="lastnews-item" key={(post.uri ?? post.link ?? post.title) + i}>
|
||||
<div class="ltopnews-content">
|
||||
<a href={post.uri ?? post.link ?? '#'} class="endnews-link">
|
||||
{post.title}
|
||||
</a>
|
||||
</div>
|
||||
</article>
|
||||
))}
|
||||
|
||||
{!hasTop && <div class="endnews-empty">Топ пока пуст</div>}
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<style>
|
||||
.endnews-container { width:100%; }
|
||||
|
||||
/* Базовые стили */
|
||||
.endnews-container {
|
||||
width: 100%;
|
||||
.endnews-header{
|
||||
padding:12px 16px;
|
||||
background:#B61D1D;
|
||||
border-radius:6px 6px 0 0;
|
||||
}
|
||||
.endnews-title{ color:#fff; margin:0; font-size:1.1rem; font-weight:600; }
|
||||
|
||||
/* Скрываем radio-кнопки */
|
||||
.endnews-tab-input{
|
||||
position:absolute;
|
||||
opacity:0;
|
||||
pointer-events:none;
|
||||
}
|
||||
|
||||
.endnews-header {
|
||||
padding: 12px 16px;
|
||||
background: #B61D1D;
|
||||
border-radius: 6px 6px 0 0;
|
||||
/* Tabs */
|
||||
.endnews-tabs{
|
||||
display:flex;
|
||||
gap:8px;
|
||||
padding:10px 12px;
|
||||
border:1px solid #ECECEC;
|
||||
border-top:none;
|
||||
background:#fff;
|
||||
}
|
||||
.endnews-tab-label{
|
||||
cursor:pointer;
|
||||
user-select:none;
|
||||
font-size:0.85rem;
|
||||
font-weight:700;
|
||||
padding:8px 10px;
|
||||
border-radius:6px;
|
||||
background:#f5f5f5;
|
||||
color:#505258;
|
||||
transition: background 0.2s, color 0.2s;
|
||||
}
|
||||
|
||||
.endnews-title {
|
||||
color: white;
|
||||
margin: 0;
|
||||
font-size: 1.1rem;
|
||||
font-weight: 600;
|
||||
/* Активный таб - используем общий сиблинг-селектор */
|
||||
#endnews-tab-news:checked ~ .endnews-tabs label[for="endnews-tab-news"],
|
||||
#endnews-tab-top:checked ~ .endnews-tabs label[for="endnews-tab-top"]{
|
||||
background:#B61D1D;
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
.latestnews-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border: 1px solid #ECECEC;
|
||||
border-top: none;
|
||||
border-radius: 0 0 6px 6px;
|
||||
background: white;
|
||||
/* list container */
|
||||
.latestnews-list{
|
||||
border:1px solid #ECECEC;
|
||||
border-top:none;
|
||||
border-radius:0 0 6px 6px;
|
||||
background:#fff;
|
||||
}
|
||||
|
||||
.latestnews-date-group {
|
||||
padding: 12px 16px;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
/* Панели скрыты по умолчанию */
|
||||
.endnews-panel{ display:none; }
|
||||
|
||||
/* Показываем нужную панель по выбранному radio */
|
||||
#endnews-tab-news:checked ~ .latestnews-list .endnews-panel--news{ display:block; }
|
||||
#endnews-tab-top:checked ~ .latestnews-list .endnews-panel--top { display:block; }
|
||||
|
||||
/* Существующий стиль списка */
|
||||
.latestnews-date-group{ padding:12px 16px; border-bottom:1px solid #f0f0f0; }
|
||||
.latestnews-date-group:last-child{ border-bottom:none; }
|
||||
|
||||
.latestnews-date{
|
||||
font-size:0.625rem;
|
||||
line-height:1.1;
|
||||
color:#505258;
|
||||
margin:0 0 0.4375rem;
|
||||
text-transform:uppercase;
|
||||
letter-spacing:0.5px;
|
||||
}
|
||||
|
||||
.latestnews-date-group:last-child {
|
||||
border-bottom: none;
|
||||
.lastnews-item{
|
||||
display:flex;
|
||||
align-items:flex-start;
|
||||
gap:12px;
|
||||
margin-bottom:10px;
|
||||
contain:content;
|
||||
}
|
||||
.lastnews-item:last-child{ margin-bottom:0; }
|
||||
|
||||
.lastnews-time{
|
||||
font-size:0.75rem;
|
||||
font-weight:700;
|
||||
line-height:1.2;
|
||||
color:#B61D1D;
|
||||
min-width:2.5rem;
|
||||
flex-shrink:0;
|
||||
margin-top:1px;
|
||||
}
|
||||
|
||||
.latestnews-date {
|
||||
font-size: 0.625rem;
|
||||
line-height: 1.1;
|
||||
color: #505258;
|
||||
margin: 0 0 0.4375rem;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.5px;
|
||||
.lastnews-content{
|
||||
line-height:1.3;
|
||||
font-weight:500;
|
||||
font-size:0.9em;
|
||||
color:#000;
|
||||
transition:color 0.2s;
|
||||
flex:1;
|
||||
}
|
||||
|
||||
.lastnews-item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
gap: 12px;
|
||||
margin-bottom: 10px;
|
||||
contain: content;
|
||||
}
|
||||
.topnews-content{
|
||||
|
||||
.lastnews-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
line-height:1.3;
|
||||
font-weight:500;
|
||||
font-size:0.9em;
|
||||
color:#000;
|
||||
transition:color 0.2s;
|
||||
margin-left: 4px;
|
||||
|
||||
.lastnews-time {
|
||||
font-size: 0.75rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
color: #B61D1D;
|
||||
min-width: 2.5rem;
|
||||
flex-shrink: 0;
|
||||
margin-top: 1px;
|
||||
}
|
||||
|
||||
.lastnews-content {
|
||||
line-height: 1.3;
|
||||
font-weight: 500;
|
||||
font-size: 0.9em;
|
||||
color: #000;
|
||||
transition: color 0.2s;
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.endnews-link {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.endnews-link:hover {
|
||||
color: #B61D1D;
|
||||
}
|
||||
|
||||
/* Десктоп: фиксированная высота со скроллом */
|
||||
@media (min-width: 1024px) {
|
||||
.endnews-container {
|
||||
height: 500px; /* Фиксированная высота */
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.latestnews-list {
|
||||
flex: 1;
|
||||
overflow-y: auto; /* Вертикальный скролл */
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
/* Кастомный скроллбар для красоты */
|
||||
.latestnews-list::-webkit-scrollbar {
|
||||
width: 6px;
|
||||
}
|
||||
|
||||
.latestnews-list::-webkit-scrollbar-track {
|
||||
background: #f5f5f5;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.latestnews-list::-webkit-scrollbar-thumb {
|
||||
background: #d0d0d0;
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.latestnews-list::-webkit-scrollbar-thumb:hover {
|
||||
background: #b0b0b0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Мобильные устройства: автоматическая высота */
|
||||
@media (max-width: 1023px) {
|
||||
.endnews-container {
|
||||
height: auto; /* Автоматическая высота */
|
||||
}
|
||||
|
||||
.latestnews-list {
|
||||
max-height: none;
|
||||
overflow: visible;
|
||||
}
|
||||
}
|
||||
|
||||
/* Планшеты (опционально) */
|
||||
@media (min-width: 768px) and (max-width: 1023px) {
|
||||
.endnews-container {
|
||||
height: auto;
|
||||
/* или можно задать другую фиксированную высоту для планшетов */
|
||||
}
|
||||
}
|
||||
|
||||
/* Анимация появления скролла (опционально) */
|
||||
.latestnews-list {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
|
||||
/* Улучшение для touch-устройств */
|
||||
@media (hover: none) and (pointer: coarse) {
|
||||
.endnews-link {
|
||||
padding: 8px 0; /* Увеличение touch-зоны */
|
||||
}
|
||||
|
||||
.lastnews-item {
|
||||
margin: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.endnews-link{ color:inherit; text-decoration:none; display:block; }
|
||||
.endnews-link:hover{ color:#B61D1D; }
|
||||
|
||||
.endnews-sub{
|
||||
margin-top:4px;
|
||||
font-size:0.75rem;
|
||||
color:#6b6d72;
|
||||
font-weight:500;
|
||||
}
|
||||
.endnews-empty{ padding:12px 16px; color:#6b6d72; font-size:0.85rem; }
|
||||
|
||||
/* Десктоп скролл */
|
||||
@media (min-width:1024px){
|
||||
.endnews-container{ height:500px; display:flex; flex-direction:column; }
|
||||
.latestnews-list{ flex:1; overflow-y:auto; overflow-x:hidden; }
|
||||
}
|
||||
@media (max-width:1023px){
|
||||
.endnews-container{ height:auto; }
|
||||
.latestnews-list{ overflow:visible; }
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
@@ -16,12 +16,13 @@ const category = mainPost?.categories?.nodes?.[0];
|
||||
const categoryName = category?.name || '';
|
||||
const categoryColor = category?.color || '#2271b1';
|
||||
|
||||
const authorName = mainPost?.author?.node?.name || '';
|
||||
|
||||
const formattedDate = postDate.toLocaleDateString('ru-RU', {
|
||||
day: 'numeric',
|
||||
month: 'short',
|
||||
year: 'numeric'
|
||||
}).replace(' г.', '');
|
||||
|
||||
---
|
||||
|
||||
<article
|
||||
@@ -30,12 +31,12 @@ const formattedDate = postDate.toLocaleDateString('ru-RU', {
|
||||
itemtype="https://schema.org/Article"
|
||||
itemid={mainPost.uri}
|
||||
>
|
||||
<a
|
||||
href={mainPost.uri}
|
||||
class="post-card-link"
|
||||
aria-label={`Читать статью: ${mainPost.title}`}
|
||||
>
|
||||
<div class="image-container">
|
||||
<div class="image-container">
|
||||
<a
|
||||
href={mainPost.uri}
|
||||
class="image-link"
|
||||
aria-label={`Читать статью: ${mainPost.title}`}
|
||||
>
|
||||
{imageUrl ? (
|
||||
<img
|
||||
src={imageUrl}
|
||||
@@ -49,35 +50,37 @@ const formattedDate = postDate.toLocaleDateString('ru-RU', {
|
||||
) : (
|
||||
<div class="image-placeholder" aria-hidden="true"></div>
|
||||
)}
|
||||
</a>
|
||||
|
||||
{categoryName && (
|
||||
<div
|
||||
class="category-badge"
|
||||
style={`background-color: ${categoryColor}`}
|
||||
>
|
||||
{categoryName}
|
||||
{categoryName && (
|
||||
<div
|
||||
class="category-badge"
|
||||
style={`background-color: ${categoryColor}`}
|
||||
>
|
||||
{categoryName}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div class="content-overlay">
|
||||
<div class="meta-overlay">
|
||||
<time datetime={isoDate} class="date-overlay">
|
||||
{formattedDate}
|
||||
</time>
|
||||
</div>
|
||||
|
||||
<h2 class="title-overlay">
|
||||
<a href={mainPost.uri} class="title-link">
|
||||
{mainPost.title}
|
||||
</a>
|
||||
</h2>
|
||||
|
||||
{authorName && (
|
||||
<div class="author-overlay">
|
||||
<Author post={mainPost} separator=" " />
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div class="content-overlay">
|
||||
<div class="meta-overlay">
|
||||
<time datetime={isoDate} class="date-overlay">
|
||||
{formattedDate}
|
||||
</time>
|
||||
</div>
|
||||
|
||||
<h2 class="title-overlay">
|
||||
{mainPost.title}
|
||||
</h2>
|
||||
|
||||
{authorName && (
|
||||
<div class="author-overlay">
|
||||
<Author post={mainPost} separator=" " />
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<meta itemprop="url" content={mainPost.uri} />
|
||||
<meta itemprop="datePublished" content={isoDate} />
|
||||
@@ -89,20 +92,12 @@ const formattedDate = postDate.toLocaleDateString('ru-RU', {
|
||||
/* ОСНОВНОЕ: ограничиваем ширину виджета */
|
||||
.main-post-widget {
|
||||
width: 100%;
|
||||
max-width: 800px; /* Вот это ключевое правило! */
|
||||
margin: 0 auto; /* Центрируем */
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
background: white;
|
||||
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.post-card-link {
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.image-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
@@ -110,6 +105,14 @@ const formattedDate = postDate.toLocaleDateString('ru-RU', {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.image-link {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.post-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -117,7 +120,7 @@ const formattedDate = postDate.toLocaleDateString('ru-RU', {
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
.post-card-link:hover .post-image {
|
||||
.image-link:hover .post-image {
|
||||
transform: scale(1.03);
|
||||
}
|
||||
|
||||
@@ -164,7 +167,16 @@ const formattedDate = postDate.toLocaleDateString('ru-RU', {
|
||||
font-size: 1.5rem;
|
||||
font-weight: 700;
|
||||
line-height: 1.3;
|
||||
}
|
||||
|
||||
.title-link {
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
transition: opacity 0.2s ease;
|
||||
}
|
||||
|
||||
.title-link:hover {
|
||||
opacity: 0.9;
|
||||
}
|
||||
|
||||
.author-overlay {
|
||||
@@ -177,7 +189,7 @@ const formattedDate = postDate.toLocaleDateString('ru-RU', {
|
||||
@media (max-width: 1023px) {
|
||||
.main-post-widget {
|
||||
border-radius: 0;
|
||||
max-width: 100%; /* На мобильных занимает всю ширину */
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.content-overlay {
|
||||
|
||||
45
src/lib/api/wp-rest-get-client.ts
Normal file
45
src/lib/api/wp-rest-get-client.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
// src/lib/api/wp-rest-get-client.ts
|
||||
|
||||
function joinUrl(base: string, path: string) {
|
||||
return `${base.replace(/\/+$/, "")}/${path.replace(/^\/+/, "")}`;
|
||||
}
|
||||
|
||||
export async function fetchWPRestGet<T = any>(
|
||||
path: string,
|
||||
query: Record<string, any> = {}
|
||||
): Promise<T> {
|
||||
const baseUrl = import.meta.env.WP_REST_BASE_URL; // например: https://site.ru
|
||||
if (!baseUrl) {
|
||||
throw new Error("WP_REST_BASE_URL is not defined in environment variables");
|
||||
}
|
||||
|
||||
const endpoint = joinUrl(baseUrl, "/wp-json/");
|
||||
const url = new URL(joinUrl(endpoint, path));
|
||||
|
||||
console.log(url);
|
||||
|
||||
const params = new URLSearchParams();
|
||||
for (const [k, v] of Object.entries(query)) {
|
||||
if (v === undefined || v === null) continue;
|
||||
if (Array.isArray(v)) v.forEach((x) => params.append(k, String(x)));
|
||||
else params.set(k, String(v));
|
||||
}
|
||||
url.search = params.toString(); // URLSearchParams -> querystring [web:87]
|
||||
|
||||
try {
|
||||
const response = await fetch(url.toString(), { method: "GET" });
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(`HTTP error ${response.status}`);
|
||||
}
|
||||
|
||||
// WP REST почти всегда JSON
|
||||
return (await response.json()) as T;
|
||||
} catch (error) {
|
||||
if (error instanceof Error) {
|
||||
console.error("WP REST GET request failed:", error.message);
|
||||
throw error;
|
||||
}
|
||||
throw new Error("Unknown error in WP REST GET request");
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@
|
||||
import { getSiteInfo } from "../lib/wp-api.js";
|
||||
import { getLatestPosts } from '@api/posts.js';
|
||||
|
||||
import { fetchWPRestGet } from "../lib/api/wp-rest-get-client";
|
||||
|
||||
|
||||
import '../styles/home.css';
|
||||
|
||||
@@ -14,6 +16,7 @@ import MainLayout from '@layouts/MainLayout.astro';
|
||||
import ContentGrid from '@components/ContentGrid.astro';
|
||||
import EndnewsList from '@components/EndnewsList.astro';
|
||||
import MainLine from '@components/MainLine.astro';
|
||||
import HomeNews from "@components/HomeNews.astro";
|
||||
|
||||
|
||||
|
||||
@@ -23,10 +26,8 @@ export const prerender = false;
|
||||
|
||||
<MainLayout
|
||||
title={site.title}
|
||||
description="Информационное агентство Деловой журнал Профиль"
|
||||
description= {site.description}
|
||||
>
|
||||
<h1>{site.title}</h1>mainline_1
|
||||
{site.description && <p>{site.description}</p>}
|
||||
|
||||
<!-- index.astro -->
|
||||
|
||||
|
||||
Reference in New Issue
Block a user