@@ -53,27 +53,73 @@
<!-- Application Info & Document Download Grid -->
< div class = " grid grid-cols-1 md:grid-cols-12 gap-8 " >
<!-- Sidebar stats / statuses -->
<!-- Sidebar stats / statuses / tabs -->
< div class = " md:col-span-4 space-y-6 " >
< div class = " bg-white rounded-3xl p-6 shadow-xl border border-slate-100/50 " >
< h3 class = " font-bold text-slate-800 text-lg mb-4 pb-2 border-b border-slate-100 " > Başvuru Detayları </ h3 >
< div class = " bg-white rounded-3xl p-4 shadow-xl border border-slate-100/50 " >
< h3 class = " font-bold text-slate-800 text-base mb-4 px-3 pb-2 border-b border-slate-100 " > Menü </ h3 >
< div class = " space-y-4 " >
< div class = " space-y-1 " role = " tablist " >
<!-- Menu Item 1 : Kişisel Bilgileriniz -->
< button type = " button " role = " tab " aria - selected = " true " data - tab - target = " personal-info " class = " tab-btn active w-full flex items-center gap-4 p-3 rounded-2xl text-left transition-all border border-transparent " >
< div class = " w-10 h-10 rounded-xl bg-blue-50 text-blue-600 flex items-center justify-center text-xl flex-shrink-0 tab-icon " >
< i class = " uil uil-user " ></ i >
</ div >
< div class = " flex-grow " >
< span class = " block text-sm font-extrabold text-slate-800 " > Kişisel Bilgiler </ span >
< span class = " block text-xs text-slate-400 font-semibold mt-0.5 " > Başvuru detayları nı z </ span >
</ div >
</ button >
<!-- Menu Item 2 : Belgeleriniz -->
< button type = " button " role = " tab " aria - selected = " false " data - tab - target = " documents " class = " tab-btn w-full flex items-center gap-4 p-3 rounded-2xl text-left transition-all border border-transparent " >
< div class = " w-10 h-10 rounded-xl bg-slate-50 text-slate-500 flex items-center justify-center text-xl flex-shrink-0 tab-icon " >
< i class = " uil uil-file-alt " ></ i >
</ div >
< div class = " flex-grow " >
< span class = " block text-sm font-extrabold text-slate-800 " > Belgeleriniz </ span >
< span class = " block text-xs text-slate-400 font-semibold mt-0.5 " > CV ve staj formları </ span >
</ div >
</ button >
<!-- Menu Item 3 : Staj Günlüğü -->
< button type = " button " role = " tab " aria - selected = " false " data - tab - target = " journal " class = " tab-btn w-full flex items-center gap-4 p-3 rounded-2xl text-left transition-all border border-transparent " >
< div class = " w-10 h-10 rounded-xl bg-slate-50 text-slate-500 flex items-center justify-center text-xl flex-shrink-0 tab-icon " >
< i class = " uil uil-github " ></ i >
</ div >
< div class = " flex-grow " >
< span class = " block text-sm font-extrabold text-slate-800 " > Staj Günlüğü </ span >
< span class = " block text-xs text-slate-400 font-semibold mt-0.5 " > GitHub commit geçmişi </ span >
</ div >
</ button >
</ div >
</ div >
</ div >
<!-- Content Panels -->
< div class = " md:col-span-8 " >
<!-- Panel 1 : Kişisel Bilgileriniz -->
< div id = " personal-info-panel " class = " tab-panel space-y-6 " >
< div class = " bg-white rounded-3xl p-6 md:p-8 shadow-xl border border-slate-100/50 " >
< h3 class = " font-bold text-slate-800 text-lg mb-6 pb-2 border-b border-slate-100 " > Kişisel Bilgileriniz </ h3 >
< div class = " grid grid-cols-1 sm:grid-cols-2 gap-6 " >
< div >
< span class = " text-xs text-slate-400 font-semibold block " > E - posta </ span >
< span class = " text-sm font-semi bold text-slate-700 block mt-0 .5 " > {{ $intern -> email }} </ span >
< span class = " text-xs text-slate-400 font-extrabold uppercase tracking-wider block " > E - posta </ span >
< span class = " text-sm font-bold text-slate-700 block mt-1 .5 " > {{ $intern -> email }} </ span >
</ div >
@ if ( $intern -> phone )
< div >
< span class = " text-xs text-slate-400 font-semibold block " > Telefon </ span >
< span class = " text-sm font-semi bold text-slate-700 block mt-0 .5 " > {{ $intern -> phone }} </ span >
< span class = " text-xs text-slate-400 font-extrabold uppercase tracking-wider block " > Telefon </ span >
< span class = " text-sm font-bold text-slate-700 block mt-1 .5 " > {{ $intern -> phone }} </ span >
</ div >
@ endif
< div >
< span class = " text-xs text-slate-400 font-semibold block " > Staj Durumu </ span >
< span class = " inline-flex mt-1.5 px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider
< span class = " text-xs text-slate-400 font-extrabold uppercase tracking-wider block " > Staj Durumu </ span >
< div class = " mt-2 " >
< span class = " inline-flex px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider
@ if ( $intern -> status === 'accepted' ) bg - green - 50 text - green - 700 border border - green - 200
@ elseif ( $intern -> status === 'rejected' ) bg - red - 50 text - red - 700 border border - red - 200
@ elseif ( $intern -> status === 'reviewed' ) bg - blue - 50 text - blue - 700 border border - blue - 200
@@ -86,33 +132,34 @@
@ else Beklemede @ endif
</ span >
</ div >
</ div >
@ if ( $intern -> internship_total_days )
< div >
< span class = " text-xs text-slate-400 font-extrabold uppercase tracking-wider block " > Toplam Süre </ span >
< span class = " text-sm font-bold text-blue-600 block mt-1.5 " > {{ $intern -> internship_total_days }} İş Günü < span class = " text-xs text-slate-400 font-normal " > ( Haftada 5 Gün ) </ span ></ span >
</ div >
@ endif
@ if ( $intern -> internship_start_date )
< div class = " border-t border-slate-100 pt-4 " >
< span class = " text-xs text-slate-400 font-semibold block " > Staj Başlangıç Tarihi </ span >
< span class = " text-sm font-semi bold text-slate-700 block mt-0 .5 " > {{ \Carbon\Carbon :: parse ( $intern -> internship_start_date ) -> format ( 'd.m.Y' ) }} </ span >
< div >
< span class = " text-xs text-slate-400 font-extrabold uppercase tracking-wider block " > Staj Başlangıç Tarihi </ span >
< span class = " text-sm font-bold text-slate-700 block mt-1 .5 " > {{ \Carbon\Carbon :: parse ( $intern -> internship_start_date ) -> format ( 'd.m.Y' ) }} </ span >
</ div >
@ endif
@ if ( $intern -> internship_end_date )
< div >
< span class = " text-xs text-slate-400 font-semibold block " > Staj Bitiş Tarihi </ span >
< span class = " text-sm font-semi bold text-slate-700 block mt-0 .5 " > {{ \Carbon\Carbon :: parse ( $intern -> internship_end_date ) -> format ( 'd.m.Y' ) }} </ span >
</ div >
@ endif
@ if ( $intern -> internship_total_days )
< div >
< span class = " text-xs text-slate-400 font-semibold block " > Toplam Süre </ span >
< span class = " text-sm font-bold text-blue-600 block mt-0.5 " > {{ $intern -> internship_total_days }} İş Günü < span class = " text-xs text-slate-400 font-normal " > ( Haftada 5 Gün ) </ span ></ span >
< span class = " text-xs text-slate-400 font-extrabold uppercase tracking-wider block " > Staj Bitiş Tarihi </ span >
< span class = " text-sm font-bold text-slate-700 block mt-1 .5 " > {{ \Carbon\Carbon :: parse ( $intern -> internship_end_date ) -> format ( 'd.m.Y' ) }} </ span >
</ div >
@ endif
</ div >
</ div >
</ div >
<!-- Document download cards -->
< div class = " md:col-span-8 space-y-6" >
<!-- Panel 2 : Belgeleriniz -->
< div id = " documents-panel " class = " tab-panel hidden space-y-6" >
< div class = " bg-white rounded-3xl p-6 md:p-8 shadow-xl border border-slate-100/50 " >
< h3 class = " font-bold text-slate-800 text-lg mb-6 pb-2 border-b border-slate-100 " > Belgeleriniz </ h3 >
@@ -301,6 +348,61 @@
</ div >
</ div >
<!-- Panel 3 : Staj Günlüğü -->
< div id = " journal-panel " class = " tab-panel hidden space-y-6 " >
< div class = " bg-white rounded-3xl p-6 md:p-8 shadow-xl border border-slate-100/50 " >
< div class = " flex flex-col sm:flex-row justify-between items-start sm:items-center gap-4 mb-6 pb-4 border-b border-slate-100 " >
< div >
< h3 class = " font-bold text-slate-800 text-lg " > Staj Günlüğü </ h3 >
< p class = " text-xs text-slate-400 mt-0.5 " > Public GitHub deponuzdaki commit geçmişi günlük olarak listelenir .</ p >
</ div >
@ if ( $intern -> github_repo )
< a href = " { { route('intern.download-journal') }} " class = " w-full sm:w-auto px-4 py-2.5 bg-green-600 hover:bg-green-700 text-white font-bold rounded-xl text-xs transition-all flex items-center justify-center gap-2 shadow-md shadow-green-500/10 " >
< i class = " uil uil-arrow-down-tray text-sm " ></ i >
< span > Günlüğü İndir ( . md ) </ span >
</ a >
@ endif
</ div >
<!-- GitHub Repository URL Configuration -->
< div class = " p-5 rounded-2xl border border-slate-100 bg-slate-50/50 mb-6 " >
< form action = " { { route('intern.save-github') }} " method = " POST " class = " space-y-4 " >
@ csrf
< div >
< label for = " github_repo " class = " block text-xs font-extrabold text-slate-500 uppercase tracking-wider mb-2 " > GitHub Public Depo URL ' si </ label >
< div class = " flex flex-col sm:flex-row gap-3 " >
< input type = " url " name = " github_repo " id = " github_repo " placeholder = " https://github.com/kullaniciadi/depo-adi " value = " { { $intern->github_repo }} " required class = " w-full px-4 py-3 rounded-xl border border-slate-200 focus:border-blue-400 focus:ring-1 focus:ring-blue-400 focus:outline-none text-sm font-semibold text-slate-700 bg-white transition-all " />
< button type = " submit " class = " px-5 py-3 bg-blue-600 hover:bg-blue-700 text-white font-bold rounded-xl text-sm transition-all shadow-md shadow-blue-500/10 flex-shrink-0 " >
{{ $intern -> github_repo ? 'Güncelle' : 'Kaydet' }}
</ button >
</ div >
< span class = " block text-xs text-slate-400 mt-2 " >< i class = " uil uil-info-circle text-blue-600 " ></ i > Deponuzun < strong > public ( herkese açık ) </ strong > olması ve en az bir commit içermesi gerekmektedir .</ span >
</ div >
</ form >
</ div >
<!-- Commits timeline / history load wrapper -->
< div id = " commits-loader " class = " hidden py-8 flex flex-col items-center justify-center " >
< div class = " animate-spin rounded-full h-8 w-8 border-b-2 border-blue-600 mb-2 " ></ div >
< span class = " text-xs text-slate-400 font-semibold " > GitHub ' dan commitler yükleniyor ...</ span >
</ div >
< div id = " commits-error " class = " hidden p-4 rounded-xl bg-red-50 border border-red-200 text-[#e31e24] text-xs font-semibold " >
</ div >
< div id = " commits-empty " class = " hidden p-6 rounded-2xl border border-slate-100 text-center text-slate-400 italic text-sm " >
Henüz hiç commit bulunamadı veya deponuz tanı mlanmadı . Lütfen deponuzu tanı mlayı n ve commitlerinizi gönderin .
</ div >
< div id = " commits-timeline " class = " hidden relative border-l-2 border-slate-100 ml-4 pl-6 space-y-6 " >
<!-- Loaded dynamically by JS -->
</ div >
</ div >
</ div >
</ div >
</ div >
</ div >
@@ -310,6 +412,161 @@
@ push ( 'styles' )
< script src = " https://cdn.tailwindcss.com " ></ script >
< script >
// Tab Switch Logic
document . addEventListener ( 'DOMContentLoaded' , function () {
const tabButtons = document . querySelectorAll ( '.tab-btn' );
const tabPanels = document . querySelectorAll ( '.tab-panel' );
tabButtons . forEach ( button => {
button . addEventListener ( 'click' , () => {
// Deactivate active tab
tabButtons . forEach ( btn => {
btn . classList . remove ( 'active' , 'bg-blue-50' , 'border-blue-100' , 'text-blue-900' );
btn . classList . add ( 'bg-transparent' , 'border-transparent' , 'text-slate-600' );
btn . querySelector ( '.tab-icon' ) . classList . remove ( 'bg-blue-600' , 'text-white' );
btn . querySelector ( '.tab-icon' ) . classList . add ( 'bg-slate-50' , 'text-slate-500' );
btn . setAttribute ( 'aria-selected' , 'false' );
});
// Hide active panels
tabPanels . forEach ( panel => {
panel . classList . add ( 'hidden' );
});
// Activate clicked tab
button . classList . add ( 'active' , 'bg-blue-50' , 'border-blue-100' , 'text-blue-900' );
button . classList . remove ( 'bg-transparent' , 'border-transparent' , 'text-slate-600' );
button . querySelector ( '.tab-icon' ) . classList . add ( 'bg-blue-600' , 'text-white' );
button . querySelector ( '.tab-icon' ) . classList . remove ( 'bg-slate-50' , 'text-slate-500' );
button . setAttribute ( 'aria-selected' , 'true' );
// Show targets panel
const targetId = button . getAttribute ( 'data-tab-target' );
const targetPanel = document . getElementById ( targetId + '-panel' );
if ( targetPanel ) {
targetPanel . classList . remove ( 'hidden' );
}
// If journal is selected, trigger GitHub commits loading
if ( targetId === 'journal' ) {
loadGithubCommits ();
}
});
});
// Handle initial state of date logic
calculateEndDateFrontend ();
});
const githubRepoUrl = @ json ( $intern -> github_repo );
function loadGithubCommits () {
const loader = document . getElementById ( 'commits-loader' );
const errorEl = document . getElementById ( 'commits-error' );
const emptyEl = document . getElementById ( 'commits-empty' );
const timelineEl = document . getElementById ( 'commits-timeline' );
if ( ! githubRepoUrl ) {
emptyEl . classList . remove ( 'hidden' );
return ;
}
loader . classList . remove ( 'hidden' );
errorEl . classList . add ( 'hidden' );
emptyEl . classList . add ( 'hidden' );
timelineEl . classList . add ( 'hidden' );
timelineEl . innerHTML = '' ;
// Parse owner and repo
let repoClean = githubRepoUrl . replace ( / https ? : \ / \ / ( www\ . ) ? github\ . com\ //i, '');
repoClean = repoClean . replace ( / \ / $ / , '' );
const parts = repoClean . split ( '/' );
if ( parts . length < 2 ) {
loader . classList . add ( 'hidden' );
errorEl . textContent = 'Github depo URL\'si çözümlenemedi. Geçerli format: https://github.com/kullanici/depo' ;
errorEl . classList . remove ( 'hidden' );
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 veya yukarı daki indirme butonunu kullanı n.' );
} else {
throw new Error ( 'GitHub API hatası : ' + response . statusText );
}
}
return response . json ();
})
. then ( commits => {
loader . classList . add ( 'hidden' );
if ( ! Array . isArray ( commits ) || commits . length === 0 ) {
emptyEl . classList . remove ( 'hidden' );
return ;
}
// Reverse to show in chronological order (Day 1, Day 2...)
commits . reverse ();
timelineEl . classList . remove ( 'hidden' );
commits . forEach (( item , index ) => {
const dayNum = index + 1 ;
const message = item . commit . message ;
const authorDate = new Date ( item . commit . author . date );
const formattedDate = authorDate . toLocaleDateString ( 'tr-TR' , {
day : '2-digit' ,
month : '2-digit' ,
year : 'numeric' ,
hour : '2-digit' ,
minute : '2-digit'
});
const shaShort = item . sha . substring ( 0 , 7 );
const commitUrl = item . html_url ;
const commitHtml = `
< div class = " relative pl-6 pb-6 last:pb-0 " >
< div class = " absolute -left-[7px] top-1.5 w-3 h-3 rounded-full bg-blue-600 shadow-sm ring-4 ring-white " ></ div >
< div class = " bg-slate-50/60 rounded-2xl p-4 border border-slate-100 hover:border-slate-200 hover:bg-slate-50 transition-all " >
< div class = " flex flex-wrap items-center justify-between gap-2 mb-2 " >
< span class = " text-xs uppercase font-extrabold tracking-wider text-blue-600 bg-blue-50 px-2.5 py-1 rounded-full " > $ { dayNum } . Gün </ span >
< div class = " flex items-center gap-2 " >
< span class = " text-xs text-slate-400 font-semibold " > $ { formattedDate } </ span >
< a href = " ${ commitUrl } " target = " _blank " class = " text-xs font-mono font-bold text-slate-500 hover:text-blue-600 bg-white px-2 py-0.5 rounded border border-slate-200/60 transition-colors flex items-center gap-1 " >
< i class = " uil uil-external-link-alt text-[10px] " ></ i >
$ { shaShort }
</ a >
</ div >
</ div >
< p class = " text-sm font-bold text-slate-700 whitespace-pre-line leading-relaxed " > $ { escapeHtml ( message )} </ p >
</ div >
</ div >
` ;
timelineEl . insertAdjacentHTML ( 'beforeend' , commitHtml );
});
})
. catch ( err => {
loader . classList . add ( 'hidden' );
errorEl . textContent = err . message || 'Bir hata oluştu.' ;
errorEl . classList . remove ( 'hidden' );
});
}
function escapeHtml ( text ) {
if ( ! text ) return '' ;
return text
. replace ( /&/ g , " & " )
. replace ( /</ g , " < " )
. replace ( />/ g , " > " )
. replace ( / " /g, " & quot ; " )
. replace ( / ' / g , " ' " );
}
function handleFileSelected ( input ) {
const fileNameElement = document . getElementById ( 'selected-file-name' );
const submitBtn = document . getElementById ( 'submit-upload-btn' );
@@ -366,11 +623,6 @@
endDateInput . value = `${yyyy}-${mm}-${dd}` ;
}
// Trigger calculation once on load if values exist
document . addEventListener ( 'DOMContentLoaded' , function () {
calculateEndDateFrontend ();
});
function copyToClipboard ( elementId , btn ) {
const text = document . getElementById ( elementId ) . textContent ;
navigator . clipboard . writeText ( text ) . then (() => {
@@ -387,6 +639,20 @@
. shadow - xl {
box - shadow : 0 1 rem 3 rem rgba ( 30 , 41 , 59 , 0.04 ) ! important ;
}
. tab - btn {
transition : all 0.2 s ease - in - out ;
}
. tab - btn : hover : not ( . active ) {
background - color : #f8fafc;
}
. tab - btn . active {
background - color : #eff6ff;
border - color : #dbeafe;
color : #1e40af !important;
}
. tab - btn . active span . text - slate - 800 {
color : #1e40af !important;
}
</ style >
@ endpush
@ endsection