Files
citrus/resources/views/livewire/intern-journal-timeline.blade.php
T

182 lines
10 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<div
x-data="{
githubRepoUrl: @js($this->githubRepo),
commitDays: [],
activeDayIndex: 0,
loading: false,
errorMsg: '',
isEmpty: false,
init() {
this.loadCommits();
},
loadCommits() {
if (!this.githubRepoUrl) {
this.isEmpty = true;
return;
}
this.loading = true;
this.errorMsg = '';
this.isEmpty = false;
this.commitDays = [];
let repoClean = this.githubRepoUrl.replace(/https?:\/\/(www\.)?github\.com\//i, '');
repoClean = repoClean.replace(/\/$/, '');
const parts = repoClean.split('/');
if (parts.length < 2) {
this.loading = false;
this.errorMsg = 'Github depo URL\'si çözümlenemedi. Geçerli format: https://github.com/kullanici/depo';
return;
}
const owner = parts[0];
const repo = parts[1].replace(/\.git$/i, '');
fetch('https://api.github.com/repos/' + owner + '/' + repo + '/commits?per_page=100')
.then(response => {
if (!response.ok) {
if (response.status === 404) throw new Error('Depo bulunamadı veya private (gizli). Deponuzun public (herkese açık) olduğundan emin olun.');
else if (response.status === 403) throw new Error('GitHub API istek limiti aşıldı. Lütfen daha sonra tekrar deneyin.');
else throw new Error('GitHub API hatası: ' + response.statusText);
}
return response.json();
})
.then(commits => {
this.loading = false;
if (!Array.isArray(commits) || commits.length === 0) {
this.isEmpty = true;
return;
}
commits.reverse();
const grouped = {};
commits.forEach(item => {
const dateStr = item.commit.author.date;
if (dateStr) {
const dateOnly = dateStr.substring(0, 10);
if (!grouped[dateOnly]) grouped[dateOnly] = [];
grouped[dateOnly].push(item);
}
});
const sortedDates = Object.keys(grouped).sort();
this.commitDays = sortedDates.map((date, index) => {
const dp = date.split('-');
return {
date: date,
dayNum: index + 1,
formattedDate: dp[2] + '.' + dp[1] + '.' + dp[0],
commits: grouped[date].map(c => ({
message: c.commit.message,
time: new Date(c.commit.author.date).toLocaleTimeString('tr-TR', { hour: '2-digit', minute: '2-digit' }),
sha: c.sha.substring(0, 7),
url: c.html_url
}))
};
});
if (this.commitDays.length === 0) {
this.isEmpty = true;
return;
}
this.activeDayIndex = 0;
})
.catch(err => {
this.loading = false;
this.errorMsg = err.message || 'Bir hata oluştu.';
});
},
get activeDay() {
return this.commitDays[this.activeDayIndex] || null;
},
navigateDay(dir) {
const n = this.activeDayIndex + dir;
if (n >= 0 && n < this.commitDays.length) this.activeDayIndex = n;
},
selectDay(i) {
this.activeDayIndex = i;
}
}"
class="mt-4"
>
{{-- Loader --}}
<div x-show="loading" x-cloak class="py-8 flex flex-col items-center justify-center">
<div class="animate-spin rounded-full h-8 w-8 border-b-2 border-primary-600 mb-2"></div>
<span class="text-xs text-gray-500 font-semibold">GitHub'dan commitler yükleniyor...</span>
</div>
{{-- Error --}}
<div x-show="errorMsg" x-cloak class="p-4 rounded-xl bg-danger-50 border border-danger-200 text-danger-600 text-xs font-semibold" x-text="errorMsg"></div>
{{-- Empty --}}
<div x-show="isEmpty && !loading" x-cloak class="p-6 rounded-2xl border border-gray-200 text-center text-gray-400 italic text-sm">
Henüz hiç commit bulunamadı veya stajyerin deposu tanımlanmadı.
</div>
{{-- Day Paginator --}}
<div x-show="commitDays.length > 0" x-cloak class="flex items-center justify-between gap-4 p-3 bg-gray-50 border border-gray-100 rounded-2xl mb-6 select-none">
<button type="button" @click="navigateDay(-1)" :disabled="activeDayIndex === 0" :class="{ 'opacity-40 cursor-not-allowed': activeDayIndex === 0 }" class="w-10 h-10 rounded-xl bg-white hover:bg-gray-100 text-gray-600 border border-gray-200 flex items-center justify-center transition-all shadow-sm">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor" class="w-5 h-5"><path stroke-linecap="round" stroke-linejoin="round" d="M15.75 19.5L8.25 12l7.5-7.5" /></svg>
</button>
<div class="flex-grow overflow-x-auto py-1" style="-ms-overflow-style: none; scrollbar-width: none;">
<div class="flex gap-2 justify-start sm:justify-center min-w-max px-2">
<template x-for="(day, index) in commitDays" :key="day.date">
<button type="button" @click="selectDay(index)" :class="index === activeDayIndex ? 'text-primary-700 bg-primary-50 border-primary-200 font-extrabold shadow-sm' : 'bg-white hover:bg-gray-50 text-gray-600 border-gray-200 font-semibold hover:text-primary-600'" class="px-5 py-2 rounded-xl transition-all flex flex-col items-center justify-center border">
<span class="text-xs" x-text="day.dayNum + '. Gün'"></span>
<span class="text-[9px] mt-0.5 opacity-70 font-medium" x-text="day.formattedDate"></span>
</button>
</template>
</div>
</div>
<button type="button" @click="navigateDay(1)" :disabled="activeDayIndex === commitDays.length - 1" :class="{ 'opacity-40 cursor-not-allowed': activeDayIndex === commitDays.length - 1 }" class="w-10 h-10 rounded-xl bg-white hover:bg-gray-100 text-gray-600 border border-gray-200 flex items-center justify-center transition-all shadow-sm">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2.5" stroke="currentColor" class="w-5 h-5"><path stroke-linecap="round" stroke-linejoin="round" d="M8.25 4.5l7.5 7.5-7.5 7.5" /></svg>
</button>
</div>
{{-- Active Day Card --}}
<div x-show="activeDay" x-cloak class="bg-white dark:bg-gray-950 border border-gray-100 dark:border-gray-800 rounded-2xl p-6 shadow-sm">
<div class="flex items-center justify-between mb-8 pb-4 border-b border-gray-100 dark:border-gray-800">
<div class="flex items-center gap-3">
<span class="text-base font-extrabold text-primary-600 bg-primary-50 dark:bg-primary-950/20 px-4 py-1.5 rounded-full" x-text="activeDay ? activeDay.dayNum + '. Gün' : ''"></span>
<span class="text-sm font-semibold text-gray-400 flex items-center gap-1">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-4 h-4 mr-1"><path stroke-linecap="round" stroke-linejoin="round" d="M6.75 3v2.25M17.25 3v2.25M3 18.75V7.5a2.25 2.25 0 012.25-2.25h13.5A2.25 2.25 0 0121 7.5v11.25m-18 0A2.25 2.25 0 005.25 21h13.5A2.25 2.25 0 0021 18.75m-18 0v-7.5A2.25 2.25 0 015.25 9h13.5A2.25 2.25 0 0121 11.25v7.5" /></svg>
<span x-text="activeDay ? activeDay.formattedDate : ''"></span>
</span>
</div>
<span class="text-xs font-bold text-gray-400 bg-gray-50 dark:bg-gray-900 border border-gray-100 dark:border-gray-800 px-2.5 py-1 rounded-lg" x-text="activeDay ? activeDay.commits.length + ' Commit' : ''"></span>
</div>
{{-- Timeline --}}
<div class="relative pl-6 sm:pl-8">
<div style="position: absolute; left: 11px; top: 8px; bottom: 8px; width: 2px; background-color: rgb(229, 231, 235);"></div>
<div class="space-y-6">
<template x-for="(commit, ci) in (activeDay ? activeDay.commits : [])" :key="ci">
<div class="relative group">
<div class="absolute top-1.5 w-6 h-6 rounded-full bg-white border-2 border-primary-500 flex items-center justify-center transition-all group-hover:bg-primary-500" style="left: -31px;">
<div class="w-2 h-2 rounded-full bg-primary-500 group-hover:bg-white transition-all"></div>
</div>
<div class="p-4 bg-gray-50/50 hover:bg-primary-50/10 border border-gray-200 hover:border-primary-100 rounded-2xl transition-all shadow-sm">
<div class="flex items-center justify-between gap-4 mb-2">
<span class="text-xs font-bold text-gray-400 flex items-center gap-1">
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="w-3.5 h-3.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 6v6h4.5m4.5 0a9 9 0 11-18 0 9 9 0 0118 0z" /></svg>
<span x-text="commit.time"></span>
</span>
<a :href="commit.url" target="_blank" class="text-xs font-mono font-bold text-primary-600 hover:text-primary-700 bg-primary-50 hover:bg-primary-100 px-2.5 py-0.5 rounded-lg border border-primary-100 transition-colors" x-text="commit.sha"></a>
</div>
<p class="text-sm font-bold text-gray-700 leading-relaxed whitespace-pre-line" x-text="commit.message"></p>
</div>
</div>
</template>
</div>
</div>
</div>
</div>