401 lines
18 KiB
Vue
401 lines
18 KiB
Vue
<script setup lang="ts">
|
||
import { storeToRefs } from "pinia";
|
||
import type { Banner } from "~~/types/banner";
|
||
import type { PostResponse } from "~~/types/post";
|
||
|
||
import { useSettingStore } from '~/stores/setting';
|
||
import { useBannerStore } from '~/stores/banner';
|
||
|
||
const _settings = useSettingStore();
|
||
const { settings } = storeToRefs(_settings);
|
||
|
||
const _bannerStore = useBannerStore();
|
||
const { banner } = storeToRefs(_bannerStore);
|
||
|
||
// API base URL — goreceli image path'ini tam URL'e donustur
|
||
const config = useRuntimeConfig();
|
||
const apiBase = (config.public.BASE_API_URL as string) || 'http://127.0.0.1:8080';
|
||
|
||
// Banner'dan gelen ilk banner'in resim URL'si (tam URL)
|
||
const bannerImageUrl = computed(() => {
|
||
const img = banner.value?.[0]?.image;
|
||
if (!img) return undefined;
|
||
if (img.startsWith('http')) return img;
|
||
return `${apiBase.replace(/\/$/, '')}${img}`;
|
||
});
|
||
|
||
// Resim path'ini tam URL'e donustur
|
||
const imgUrl = (path: string) => {
|
||
if (!path) return '';
|
||
if (path.startsWith('http')) return path;
|
||
return `${apiBase.replace(/\/$/, '')}${path}`;
|
||
};
|
||
|
||
// Tarihi gg.aa.yyyy formatina cevir
|
||
const formatDate = (dateStr?: string) => {
|
||
if (!dateStr) return '';
|
||
return new Date(dateStr).toLocaleDateString('tr-TR', {
|
||
day: '2-digit', month: 'long', year: 'numeric'
|
||
});
|
||
};
|
||
|
||
const breadcrumbs = [
|
||
{ label: 'Home', href: '#' },
|
||
{ label: 'Blog' }
|
||
]
|
||
|
||
useSeoMeta({
|
||
title: 'Blog',
|
||
description: 'En son haberler ve makaleler',
|
||
})
|
||
|
||
// Postlari API'dan cek
|
||
const route = useRoute();
|
||
const page = computed(() => Number(route.query.page) || 1);
|
||
|
||
const { data: postsData, refresh } = await useFetch<PostResponse>(() => `${apiBase}/api/v1/posts?page=${page.value}`);
|
||
const posts = computed(() => postsData.value?.data ?? []);
|
||
const postMeta = computed(() => postsData.value?.meta);
|
||
|
||
// Sayfa degistirme fonksiyonu
|
||
const changePage = (newPage: number) => {
|
||
if (newPage < 1 || (postMeta.value && newPage > Math.ceil(postMeta.value.total / postMeta.value.per_page))) return;
|
||
navigateTo({ query: { ...route.query, page: newPage } });
|
||
};
|
||
|
||
// Toplam sayfa sayisi
|
||
const totalPages = computed(() => {
|
||
if (!postMeta.value) return 1;
|
||
return Math.ceil(postMeta.value.total / postMeta.value.per_page);
|
||
});
|
||
</script>
|
||
|
||
<template>
|
||
<div>
|
||
<PageTitle title="Blog" subtitle="Our Latest News" :breadcrumbs="breadcrumbs" :image="bannerImageUrl"
|
||
:color="banner?.[0]?.color" imageType="background" />
|
||
<!-- Content
|
||
============================================= -->
|
||
<section id="content">
|
||
<div class="content-wrap">
|
||
<div class="container">
|
||
<div class="row gx-5 col-mb-80">
|
||
<!-- Post Content
|
||
============================================= -->
|
||
<main class="postcontent col-lg-9">
|
||
<!-- Postlar API'dan geliyor -->
|
||
<div id="posts" class="row gutter-40">
|
||
|
||
<div v-for="post in posts" :key="post.ID" class="entry col-12">
|
||
<div class="grid-inner row g-0">
|
||
<!-- Sol: Post resmi -->
|
||
<div class="col-md-4">
|
||
<div class="entry-image">
|
||
<NuxtLink :to="`/blog/${post.slug}`">
|
||
<img :src="imgUrl(post.images_min || post.images)" :alt="post.title"
|
||
style="width:100%; height:200px; object-fit:cover;" />
|
||
</NuxtLink>
|
||
</div>
|
||
</div>
|
||
<!-- Sag: Post icerigi -->
|
||
<div class="col-md-8 ps-md-4">
|
||
<div class="entry-title title-sm">
|
||
<h2>
|
||
<NuxtLink :to="`/blog/${post.slug}`">{{ post.title }}</NuxtLink>
|
||
</h2>
|
||
</div>
|
||
<div class="entry-meta">
|
||
<ul>
|
||
<li><i class="uil uil-schedule" /> {{ formatDate(post.UpdatedAt || post.CreatedAt) }}
|
||
<span v-if="post.UpdatedAt && post.UpdatedAt !== post.CreatedAt"
|
||
style="font-size: 0.8em; opacity: 0.8;">
|
||
(Güncellendi)
|
||
</span>
|
||
</li>
|
||
<li v-if="post.categories?.length">
|
||
<i class="uil uil-folder-open" />
|
||
<template v-for="(cat, ci) in post.categories" :key="cat.ID">
|
||
<NuxtLink :to="`/kategori/${cat.slug}`">{{ cat.title }}</NuxtLink>
|
||
<span v-if="ci < post.categories.length - 1">, </span>
|
||
</template>
|
||
</li>
|
||
<li v-if="post.tags?.length">
|
||
<i class="uil uil-tag" />
|
||
<template v-for="(tag, ti) in post.tags" :key="tag.ID">
|
||
<span>{{ tag.name }}</span>
|
||
<span v-if="ti < post.tags.length - 1">, </span>
|
||
</template>
|
||
</li>
|
||
</ul>
|
||
</div>
|
||
<div class="entry-content">
|
||
<p>{{ post.content.substring(0, 150) }}{{ post.content.length > 150 ? '...' : '' }}</p>
|
||
<NuxtLink :to="`/blog/${post.slug}`" class="more-link">Devamını Oku</NuxtLink>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Post bulunamadiysa -->
|
||
<div v-if="!posts.length" class="col-12 text-center py-5">
|
||
<p>Henüz gönderi bulunamadı.</p>
|
||
</div>
|
||
|
||
</div><!-- #posts end -->
|
||
|
||
<!-- Pager
|
||
============================================= -->
|
||
<div v-if="totalPages > 1" class="d-flex justify-content-between mt-5">
|
||
<button class="btn btn-outline-secondary" :disabled="page <= 1" @click="changePage(page - 1)">
|
||
← Daha Eski
|
||
</button>
|
||
<div class="align-self-center">
|
||
Sayfa {{ page }} / {{ totalPages }}
|
||
</div>
|
||
<button class="btn btn-outline-dark" :disabled="page >= totalPages" @click="changePage(page + 1)">
|
||
Daha Yeni →
|
||
</button>
|
||
</div>
|
||
<!-- .pager end -->
|
||
|
||
</main><!-- .postcontent end -->
|
||
|
||
<!-- Sidebar
|
||
============================================= -->
|
||
<aside class="sidebar col-lg-3">
|
||
<div class="sidebar-widgets-wrap">
|
||
|
||
|
||
|
||
|
||
|
||
<div class="widget">
|
||
|
||
<ul id="canvas-tab" class="nav canvas-tabs tabs nav-tabs size-sm mb-3" role="tablist">
|
||
<li class="nav-item" role="presentation">
|
||
<button id="canvas-tab-1" class="nav-link active" data-bs-toggle="pill" data-bs-target="#tab-1"
|
||
type="button" role="tab" aria-controls="canvas-tab-1" aria-selected="true">Popular</button>
|
||
</li>
|
||
<li class="nav-item" role="presentation">
|
||
<button id="canvas-tab-2" class="nav-link" data-bs-toggle="pill" data-bs-target="#tab-2"
|
||
type="button" role="tab" aria-controls="canvas-tab-2" aria-selected="false">Recents</button>
|
||
</li>
|
||
<li class="nav-item" role="presentation">
|
||
<button id="canvas-tab-3" class="nav-link uil uil-comments-alt" data-bs-toggle="pill"
|
||
data-bs-target="#tab-3" type="button" role="tab" aria-controls="canvas-tab-3"
|
||
aria-selected="false" />
|
||
</li>
|
||
</ul>
|
||
|
||
<div id="canvas-TabContent" class="tab-content">
|
||
|
||
<div id="tab-1" class="tab-pane show active" role="tabpanel" aria-labelledby="canvas-tab-1"
|
||
tabindex="0">
|
||
<div id="popular-post-list-sidebar" class="posts-sm row col-mb-30">
|
||
<div class="entry col-12">
|
||
<div class="grid-inner row g-0">
|
||
<div class="col-auto">
|
||
<div class="entry-image">
|
||
<a href="#"><img class="rounded-circle" src="/images/magazine/small/3.jpg"
|
||
alt="Image"></a>
|
||
</div>
|
||
</div>
|
||
<div class="col ps-3">
|
||
<div class="entry-title">
|
||
<h4><a href="#">Lorem ipsum dolor sit amet, consectetur</a></h4>
|
||
</div>
|
||
<div class="entry-meta">
|
||
<ul>
|
||
<li><i class="uil uil-comments-alt" /> 35 Comments</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="entry col-12">
|
||
<div class="grid-inner row g-0">
|
||
<div class="col-auto">
|
||
<div class="entry-image">
|
||
<a href="#"><img class="rounded-circle" src="/images/magazine/small/2.jpg"
|
||
alt="Image"></a>
|
||
</div>
|
||
</div>
|
||
<div class="col ps-3">
|
||
<div class="entry-title">
|
||
<h4><a href="#">Elit Assumenda vel amet dolorum quasi</a></h4>
|
||
</div>
|
||
<div class="entry-meta">
|
||
<ul>
|
||
<li><i class="uil uil-comments-alt" /> 24 Comments</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="entry col-12">
|
||
<div class="grid-inner row g-0">
|
||
<div class="col-auto">
|
||
<div class="entry-image">
|
||
<a href="#"><img class="rounded-circle" src="/images/magazine/small/1.jpg"
|
||
alt="Image"></a>
|
||
</div>
|
||
</div>
|
||
<div class="col ps-3">
|
||
<div class="entry-title">
|
||
<h4><a href="#">Debitis nihil placeat, illum est nisi</a></h4>
|
||
</div>
|
||
<div class="entry-meta">
|
||
<ul>
|
||
<li><i class="uil uil-comments-alt" /> 19 Comments</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="tab-2" class="tab-pane" role="tabpanel" aria-labelledby="canvas-tab-2" tabindex="0">
|
||
<div id="recent-post-list-sidebar" class="posts-sm row col-mb-30">
|
||
<div class="entry col-12">
|
||
<div class="grid-inner row g-0">
|
||
<div class="col-auto">
|
||
<div class="entry-image">
|
||
<a href="#"><img class="rounded-circle" src="/images/magazine/small/1.jpg"
|
||
alt="Image"></a>
|
||
</div>
|
||
</div>
|
||
<div class="col ps-3">
|
||
<div class="entry-title">
|
||
<h4><a href="#">Lorem ipsum dolor sit amet, consectetur</a></h4>
|
||
</div>
|
||
<div class="entry-meta">
|
||
<ul>
|
||
<li>10th July 2021</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="entry col-12">
|
||
<div class="grid-inner row g-0">
|
||
<div class="col-auto">
|
||
<div class="entry-image">
|
||
<a href="#"><img class="rounded-circle" src="/images/magazine/small/2.jpg"
|
||
alt="Image"></a>
|
||
</div>
|
||
</div>
|
||
<div class="col ps-3">
|
||
<div class="entry-title">
|
||
<h4><a href="#">Elit Assumenda vel amet dolorum quasi</a></h4>
|
||
</div>
|
||
<div class="entry-meta">
|
||
<ul>
|
||
<li>10th July 2021</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="entry col-12">
|
||
<div class="grid-inner row g-0">
|
||
<div class="col-auto">
|
||
<div class="entry-image">
|
||
<a href="#"><img class="rounded-circle" src="/images/magazine/small/3.jpg"
|
||
alt="Image"></a>
|
||
</div>
|
||
</div>
|
||
<div class="col ps-3">
|
||
<div class="entry-title">
|
||
<h4><a href="#">Debitis nihil placeat, illum est nisi</a></h4>
|
||
</div>
|
||
<div class="entry-meta">
|
||
<ul>
|
||
<li>10th July 2021</li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<div id="tab-3" class="tab-pane" role="tabpanel" aria-labelledby="canvas-tab-3" tabindex="0">
|
||
<div id="recent-comments-list-sidebar" class="posts-sm row col-mb-30">
|
||
<div class="entry col-12">
|
||
<div class="grid-inner row g-0">
|
||
<div class="col-auto">
|
||
<div class="entry-image">
|
||
<a href="#"><img class="rounded-circle" src="/images/icons/avatar.jpg"
|
||
alt="User Avatar"></a>
|
||
</div>
|
||
</div>
|
||
<div class="col ps-3">
|
||
<strong>John Doe:</strong> Veritatis recusandae sunt repellat distinctio...
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="entry col-12">
|
||
<div class="grid-inner row g-0">
|
||
<div class="col-auto">
|
||
<div class="entry-image">
|
||
<a href="#"><img class="rounded-circle" src="/images/icons/avatar.jpg"
|
||
alt="User Avatar"></a>
|
||
</div>
|
||
</div>
|
||
<div class="col ps-3">
|
||
<strong>Mary Jane:</strong> Possimus libero, earum officia architecto maiores....
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="entry col-12">
|
||
<div class="grid-inner row g-0">
|
||
<div class="col-auto">
|
||
<div class="entry-image">
|
||
<a href="#"><img class="rounded-circle" src="/images/icons/avatar.jpg"
|
||
alt="User Avatar"></a>
|
||
</div>
|
||
</div>
|
||
<div class="col ps-3">
|
||
<strong>Site Admin:</strong> Deleniti magni labore laboriosam odio...
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
<div class="widget">
|
||
<h4>Tag Cloud</h4>
|
||
<div class="tagcloud">
|
||
<a href="#">general</a>
|
||
<a href="#">videos</a>
|
||
<a href="#">music</a>
|
||
<a href="#">media</a>
|
||
<a href="#">photography</a>
|
||
<a href="#">parallax</a>
|
||
<a href="#">ecommerce</a>
|
||
<a href="#">terms</a>
|
||
<a href="#">coupons</a>
|
||
<a href="#">modern</a>
|
||
</div>
|
||
|
||
</div>
|
||
|
||
</div>
|
||
</aside><!-- .sidebar end -->
|
||
</div>
|
||
|
||
</div>
|
||
</div>
|
||
</section><!-- #content end -->
|
||
</div>
|
||
</template>
|
||
|
||
<style scoped></style> |