Skip to content

feat: PDF generation overhaul with shared utility and compact A4-optimized design#5

Draft
Copilot wants to merge 7 commits into
mainfrom
copilot/improve-pdf-generation
Draft

feat: PDF generation overhaul with shared utility and compact A4-optimized design#5
Copilot wants to merge 7 commits into
mainfrom
copilot/improve-pdf-generation

Conversation

Copilot AI commented May 2, 2026

Copy link
Copy Markdown
Original prompt

PDF Oluşturma İyileştirmesi

Sorunlar:

  1. Okunurluğu zayıf: Yazı türleri, boyutlar, renkler optimize edilmemiş
  2. A4 Tasarrufu Yok: Sayfa yönetimi düşük, alan israfı yüksek
  3. Uzun Tablolar: Çok veri içeren PDF'ler kötü formatlanıyor
  4. Yatay Format Eksikliği: Geniş tablolar dikey formatda okunamıyor

Çözüm:

  1. PDF Utility Dosyası Oluştur (utils/pdfGenerator.js):

    • Standart PDF ayarları (yazı, renkler, spacing)
    • Otomatik sayfa yönetimi fonksiyonları
    • Tablo çizme helper fonksiyonları
    • Dinamik layout seçimi (portrait/landscape)
  2. Akıllı Layout Seçimi:

    • Eğer sütun sayısı > 4 veya toplam veri genişliği > A4'e sığmıyorsa → Yatay (Landscape)
    • Aksı takdirde → Dikey (Portrait)
  3. Font & Typography İyileştirmesi:

    • Başlık: 14pt, Bold, Koyu mavi
    • Alt başlık: 11pt, Bold, Koyu gri
    • İçerik: 9pt, Regular, Siyah
    • Tablo başlığı: 9pt, Bold, Beyaz/Mavi arka plan
  4. Sayfa Tasarrufu:

    • Margin: 40px (compact)
    • Row height: 20px (düşük)
    • Satır arası: 2px
    • Otomatik sayfa kesme ve başlık tekrarı

Uygulanacak Dosyalar:

  • routes/organisations.js - Tüm PDF endpoint'lerinde kullan
  • routes/tournamentMatches.js - Eğer varsa
  • routes/matAssignments.js - Eğer varsa

Çıktılar:

  • ✅ Okunabilir, profesyonel PDF'ler
  • ✅ A4 kağıdına optimizasyon
  • ✅ Otomatik yatay format seçimi
  • ✅ Konsistent tasarım
  • ✅ Minimum kağıt kullanımı

The following is the prior conversation context from the user's chat exploration (may be truncated):

Assistant: ```bash
node -e "
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const User = require('./models/user');
const Role = require('./models/role');
const City = require('./models/city');
const Club = require('./models/club');
require('dotenv').config();

mongoose.connect(process.env.MONGO_URI).then(async () => {
const roles = ['Admin', 'Coach', 'Referee', 'Athlete', 'Representative'];
const cities = await City.find().limit(5);
const clubs = await Club.find().limit(5);

if (cities.length === 0 || clubs.length === 0) {
console.log('❌ Şehir veya Kulüp bulunamadı. Önce bunları oluştur!');
process.exit(1);
}

let createdCount = 0;
const usersToCreate = [];

for (const roleName of roles) {
const role = await Role.findOne({ name: roleName });

// Her rolden 100 kullanıcı oluştur
for (let i = 1; i <= 100; i++) {
  const identityNumber = String(10000000000 + (roles.indexOf(roleName) * 100) + i).slice(-11);
  const hashedPassword = await bcrypt.hash('123456', 10);
  
  const randomCity = cities[Math.floor(Math.random() * cities.length)];
  const randomClub = clubs[Math.floor(Math.random() * clubs.length)];
  
  usersToCreate.push({
    name: roleName + ' Test',
    surname: 'Kullanıcı ' + i,
    email: roleName.toLowerCase() + i + '@test.local',
    identityNumber: identityNumber,
    password: hashedPassword,
    role: role._id,
    gender: Math.random() > 0.5 ? 'Erkek' : 'Kadın',
    birthDate: new Date('1990-01-01'),
    fatherName: 'Baba ' + i,
    motherName: 'Anne ' + i,
    city: randomCity._id,
    club: randomClub._id,
    mobilePhone: '555' + String(1000000 + i).slice(-7),
    nationality: 'Türk',
    isAthlete: roleName === 'Athlete',
    isCoach: roleName === 'Coach',
    isReferee: roleName === 'Referee',
    isProvincialRepresentative: roleName === 'Representative',
    createdAt: new Date(),
    addedAt: new Date()
  });
}

}

await User.insertMany(usersToCreate);
console.log('✅ ' + usersToCreate.length + ' test kullanıcısı başarıyla oluşturuldu!');
console.log('📊 Dağılım: Her rolden 100 kullanıcı (Toplam: 500)');

process.exit(0);
});
"


Bu komut:
- ✅ **Admin:** 100 kullanıcı
- ✅ **Coach:** 100 kullanıcı  
- ✅ **Referee:** 100 kullanıcı
- ✅ **Athlete:** 100 kullanıcı
- ✅ **Representative:** 100 kullanıcı

**Toplam: 500 test kullanıcısı** 🎉

Hepsine şifre: `123456`

Şehir ve kulüpler random atanacak. Çalıştır!

User: şehir ve kulüp oluştur önce tüm şehirleri ekle (81 il) ve  tüm şehirlere bağlı {city.id}gençlik ve spor kulübü ekle 

Assistant: Perfect! Şimdi bu script'i çalıştır:

```bash
node scripts/seedCitiesAndClubs.js

Bu komut:

  • 81 şehir oluşturacak
  • 81 kulüp oluşturacak (Her şehire "Gençlik ve Spor Kulübü")
  • ✅ Kulüpler otomatik olarak şehirlere bağlanacak

Tamamlandıktan sonra test kullanıcılarını eklemek için:

node -e "
const mongoose = require('mongoose');
const bcrypt = require('bcrypt');
const User = require('./models/user');
const Role = require('./models/role');
const City = require('./models/city');
const Club = require('./models/club');
require('dotenv').config();

mongoose.connect(process.env.MONGO_URI).then(async () => {
  const roles = ['Admin', 'Coach', 'Referee', 'Athlete', 'Representative'];
  const cities = await City.find();
  const clubs = await ...

</details>



<!-- START COPILOT CODING AGENT SUFFIX -->

*This pull request was created from Copilot chat.*
>

Copilot AI and others added 2 commits May 2, 2026 17:31
…nisations.js

- Add utils/pdfGenerator.js with shared design tokens (colors, fonts, layout),
  turkishToAscii helper, smart layout selection (landscape if >5 cols or width >515px),
  createDoc/drawPageHeader/drawTableHeaders/drawTableRow/drawGroupHeader/
  drawPageFooter/drawSignatureArea utility functions
- Refactor /participants/export: uses utility, 8-col landscape, 40px margins,
  20px row height, compact 60px header, white-on-blue table headers
- Refactor /weighing-list: uses utility, 5-col portrait, compact design,
  signature area on same page
- Refactor /all-weighing-list: uses utility, 5-col portrait, grouped by
  weight category, signature area on last page
- Remove duplicate color/font/turkishToAscii definitions from route handlers

Agent-Logs-Url: https://github.com/mvtandas/kuras-backend/sessions/79e5a5f1-4088-42b5-bc9b-794d639427d8

Co-authored-by: Xhanio57 <179158957+Xhanio57@users.noreply.github.com>
Copilot AI changed the title [WIP] Enhance PDF generation for better readability and layout feat: PDF generation overhaul with shared utility and compact A4-optimized design May 2, 2026
Copilot AI requested a review from Xhanio57 May 2, 2026 17:33
Copilot AI and others added 2 commits May 2, 2026 17:54
- utils/pdfGenerator.js: add COMPACT_LAYOUT (30px margin, 15px rows, 28px header),
  drawCompactPageHeader, drawCompactTableHeaders, drawCompactRow,
  drawCompactGroupHeader, drawCompactSignature functions → 47 rows/page vs ~31
- routes/organisations.js: weighing-list + all-weighing-list use compact functions;
  import new compact utilities; signature on last page only
- routes/tournamentMatches.js: add GET /:id/fixture-pdf (A4 landscape bracket tree
  with group labels A-H, match circles, winner names, score notes, results table,
  repechage section for double elimination)"

Agent-Logs-Url: https://github.com/mvtandas/kuras-backend/sessions/370528a9-6d92-49f5-867c-addbcf6f4c27

Co-authored-by: Xhanio57 <179158957+Xhanio57@users.noreply.github.com>
… judo bracket style)

- Switch from landscape to portrait A4
- Remove all colored boxes - plain bold text header on white background
- Match circles: white fill, black border (not gray)
- Lines: thin black (0.6pt) everywhere
- Refactored into drawBracketMatch() helper to avoid duplication
- Player format: 'Name, City/Club' matching reference style
- Score/notes shown centered below match circle in gray
- Winner surname (bold) on output line after circle
- Results table: plain black borders, no colored header row
- Repechage section: same visual style as main bracket, light italic label"

Agent-Logs-Url: https://github.com/mvtandas/kuras-backend/sessions/c4ebb451-a50b-406e-a801-7454e27f1ff1

Co-authored-by: Xhanio57 <179158957+Xhanio57@users.noreply.github.com>
- addNoteOnce: fix broken regex literals (\\s → \s inside /.../ literals)
- processAdvancement: guard loser bracket rebuild so completed matches
  are not wiped on every GET request
- createSingleEliminationBrackets: fix wrong nextMatchNumber formula
  for rounds 2+ (use roundStart-based indexing instead of broken
  Math.ceil(matchNumber/2)+totalMatches+pow formula)

Agent-Logs-Url: https://github.com/mvtandas/kuras-backend/sessions/a00c39eb-9501-400c-82fd-f87da6216aab

Co-authored-by: Xhanio57 <179158957+Xhanio57@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants