from reportlab.lib.pagesizes import A4
from reportlab.lib import colors
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph, Spacer, Image
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm, inch
from reportlab.lib.enums import TA_CENTER
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
import base64
import os
# Register custom fonts if available, else use standard fonts
def register_fonts():
try:
pdfmetrics.registerFont(TTFont('SweetPoppy', 'Sweet_Poppy.ttf'))
pdfmetrics.registerFont(TTFont('CandyBeans', 'Candy_Beans.otf'))
return 'SweetPoppy', 'CandyBeans'
except Exception as e:
print(f"Custom fonts not loaded ({e}), using Helvetica fallback.")
# No need to register Helvetica, use default names
return 'Helvetica-Bold', 'Helvetica'
font_header, font_body = register_fonts()
# Create base64 encoded sticker images (simplified for demonstration)
def create_sticker_images():
sticker_dir = "/mnt/data/stickers"
os.makedirs(sticker_dir, exist_ok=True)
# Star sticker (truncated for brevity)
star_b64 = "iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAACXBIWXMAAAsTAAALEwEAmpwYAAABYklEQVRYhe3WQU7CUBSG8a9vQdIFuAQX4BJcgktwCS7BJbgEl+ASXII2kAY0kRgT4wLcQY0LcAdtDZg8yKXl0b7yXmE4XzK5mTQz/5l7bw7/3QJ4BJ6AL+AL2ANbYBXvPwF3sTbVFsAD8A58A5/AO7AH3oAX4BZYAbfx2dQzqXYLvMR5P4C3OP8eeAWeY+0BuI+1qXYHPAPvce5dnH8Xa9tYu4vPpp5JtTvgEXiOc+/j3PtY28baXXw29Uyq3QL3wGOcexvn38XaNtbu4rOpZ1JtA9wA1zH3Ns6/jbVtrN3FZ1PPpNp1zF3F3Ns4/zbWtrF2F59NPZNqVzF3FXNv4/zbWNvG2l18NvVMql3F3DrmXsf5N7G2ibXr+GzqmVS7jLl1zL2O829ibRNrN/HZ1DOpdvmrdhlzVzH3Ks6/jrVNrF3FZ1PPpNrVr9pVzF3F3Ks4/zrWNrF2HZ9NPZNqN79q1zF3HXOv4/zrWNvE2k18NvVMqt3+qt0C99C9JjQZcR0AAAAASUVORK5CYII="
with open(os.path.join(sticker_dir, "star.png"), "wb") as f:
f.write(base64.b64decode(star_b64))
# Heart sticker
heart_b64 = "iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAACXBIWXMAAAsTAAALEwEAmpwYAAABYklEQVRYhe3WQU7CUBSG8a9vQdIFuAQX4BJcgktwCS7BJbgEl+ASXII2kAY0kRgT4wLcQY0LcAdtDZg8yKXl0b7yXmE4XzK5mTQz/5l7bw7/3QJ4BJ6AL+AL2ANbYBXvPwF3sTbVFsAD8A58A5/AO7AH3oAX4BZYAbfx2dQzqXYLvMR5P4C3OP8eeAWeY+0BuI+1qXYHPAPvce5dnH8Xa9tYu4vPpp5JtTvgEXiOc+/j3PtY28baXXw29Uyq3QL3wGOcexvn38XaNtbu4rOpZ1JtA9wA1zH3Ns6/jbVtrN3FZ1PPpNp1zF3F3Ns4/zbWtrF2F59NPZNqVzF3FXNv4/zbWNvG2l18NvVMql3F3DrmXsf5N7G2ibXr+GzqmVS7jLl1zL2O829ibRNrN/HZ1DOpdvmrdhlzVzH3Ks6/jrVNrF3FZ1PPpNrVr9pVzF3F3Ks4/zrWNrF2HZ9NPZNqN79q1zF3HXOv4/zrWNvE2k18NvVMqt3+qt0C99C9JjQZcR0AAAAASUVORK5CYII="
with open(os.path.join(sticker_dir, "heart.png"), "wb") as f:
f.write(base64.b64decode(heart_b64))
# Flower sticker
flower_b64 = "iVBORw0KGgoAAAANSUhEUgAAACgAAAAoCAYAAACM/rhtAAAACXBIWXMAAAsTAAALEwEAmpwYAAABYklEQVRYhe3WQU7CUBSG8a9vQdIFuAQX4BJcgktwCS7BJbgEl+ASXII2kAY0kRgT4wLcQY0LcAdtDZg8yKXl0b7yXmE4XzK5mTQz/5l7bw7/3QJ4BJ6AL+AL2ANbYBXvPwF3sTbVFsAD8A58A5/AO7AH3oAX4BZYAbfx2dQzqXYLvMR5P4C3OP8eeAWeY+0BuI+1qXYHPAPvce5dnH8Xa9tYu4vPpp5JtTvgEXiOc+/j3PtY28baXXw29Uyq3QL3wGOcexvn38XaNtbu4rOpZ1JtA9wA1zH3Ns6/jbVtrN3FZ1PPpNp1zF3F3Ns4/zbWtrF2F59NPZNqVzF3FXNv4/zbWNvG2l18NvVMql3F3DrmXsf5N7G2ibXr+GzqmVS7jLl1zL2O829ibRNrN/HZ1DOpdvmrdhlzVzH3Ks6/jrVNrF3FZ1PPpNrVr9pVzF3F3Ks4/zrWNrF2HZ9NPZNqN79q1zF3HXOv4/zrWNvE2k18NvVMqt3+qt0C99C9JjQZcR0AAAAASUVORK5CYII="
with open(os.path.join(sticker_dir, "flower.png"), "wb") as f:
f.write(base64.b64decode(flower_b64))
return sticker_dir
sticker_dir = create_sticker_images()
file_path = "cute_fitness_tracker.pdf"
# Custom DocTemplate to paint pastel pink background on every page
class PastelPinkTemplate(SimpleDocTemplate):
def __init__(self, filename, **kw):
super().__init__(filename, **kw)
self.pastel_pink = colors.HexColor("#FFD1DC")
def beforePage(self):
self.canv.saveState()
self.canv.setFillColor(self.pastel_pink)
self.canv.rect(0, 0, self.pagesize[0], self.pagesize[1], fill=1, stroke=0)
self.canv.restoreState()
doc = PastelPinkTemplate(
file_path,
pagesize=A4,
leftMargin=1.5*cm,
rightMargin=1.5*cm,
topMargin=1.5*cm,
bottomMargin=1.5*cm
)
# Styles
styles = getSampleStyleSheet()
styles.add(ParagraphStyle(
name='Header',
fontName=font_header,
fontSize=28,
textColor=colors.HexColor('#FF5C8D'),
alignment=TA_CENTER,
spaceAfter=12
))
styles.add(ParagraphStyle(
name='Subheader',
fontName=font_header,
fontSize=18,
textColor=colors.HexColor('#FF85A2'),
alignment=TA_CENTER,
spaceAfter=8
))
styles.add(ParagraphStyle(
name='WeekTitle',
fontName=font_body,
fontSize=16,
textColor=colors.HexColor('#D291BC'),
alignment=TA_CENTER,
spaceAfter=10
))
styles.add(ParagraphStyle(
name='Body',
fontName=font_body,
fontSize=12,
textColor=colors.HexColor('#8A5362'),
leading=16
))
styles.add(ParagraphStyle(
name='TableHeader',
fontName=font_header,
fontSize=12,
textColor=colors.white,
alignment=TA_CENTER
))
styles.add(ParagraphStyle(
name='TableCell',
fontName=font_body,
fontSize=11,
textColor=colors.HexColor('#8A5362'),
alignment=TA_CENTER
))
styles.add(ParagraphStyle(
name='Footer',
fontName=font_body,
fontSize=10,
textColor=colors.HexColor('#FF85A2'),
alignment=TA_CENTER
))
elements = []
# Title with stars on sides
title_table = Table([
[Image(os.path.join(sticker_dir, "star.png"), width=0.6*inch, height=0.6*inch),
Paragraph("8-Week Fitness Journey Tracker", styles['Header']),
Image(os.path.join(sticker_dir, "star.png"), width=0.6*inch, height=0.6*inch)]
], colWidths=[1.5*cm, None, 1.5*cm])
title_table.setStyle(TableStyle([
('ALIGN', (0,0), (-1,-1), 'CENTER'),
('VALIGN', (0,0), (-1,-1), 'MIDDLE'),
('BACKGROUND', (0,0), (-1,-1), colors.transparent),
]))
elements.append(title_table)
elements.append(Spacer(1, 10))
# Subtitle
elements.append(Paragraph("Your Path to a Healthier, Happier You", styles['Subheader']))
elements.append(Spacer(1, 5))
# Decorative divider
divider = Table([["♡" * 25]], colWidths=[doc.width])
divider.setStyle(TableStyle([
('TEXTCOLOR', (0,0), (0,0), colors.HexColor('#FF85A2')),
('ALIGN', (0,0), (0,0), 'CENTER'),
('FONTSIZE', (0,0), (0,0), 10),
('BACKGROUND', (0,0), (0,0), colors.transparent),
]))
elements.append(divider)
elements.append(Spacer(1, 15))
# Intro text with heart sticker
intro_table = Table([
[Image(os.path.join(sticker_dir, "heart.png"), width=0.7*inch, height=0.7*inch),
Paragraph(
"Welcome to your fitness adventure! This tracker will help you follow your 8-week journey step-by-step. "
"Check off your meals, workouts, and progress each day. Stay consistent and you'll see amazing results! "
"Remember to celebrate every small victory along the way! 💖",
styles['Body']
)]
], colWidths=[1.5*inch, None])
intro_table.setStyle(TableStyle([
('VALIGN', (0,0), (-1,-1), 'TOP'),
('BACKGROUND', (0,0), (-1,-1), colors.transparent),
]))
elements.append(intro_table)
elements.append(Spacer(1, 20))
# Table headers (5 columns to match weekly data)
table_headers = [
Paragraph("Day", styles['TableHeader']),
Paragraph("Meal Plan", styles['TableHeader']),
Paragraph("Workout", styles['TableHeader']),
Paragraph("Completed", styles['TableHeader']),
Image(os.path.join(sticker_dir, "flower.png"), width=0.5*inch, height=0.5*inch)
]
# Workout schedule for the week
workout_schedule = [
"Full Body Strength",
"Cardio + Core",
"Rest / Recovery",
"Lower Body Focus",
"Upper Body + Core",
"Cardio Circuit",
"Yoga & Stretching"
]
# Loop for 8 weeks
for week in range(1, 9):
# Week title
week_title = Table([[Paragraph(f"Week {week}", styles['WeekTitle'])]], colWidths=[doc.width])
elements.append(week_title)
# Build week table data including headers for clarity
week_table_data = [table_headers]
for day in range(1, 8):
sticker = Image(os.path.join(sticker_dir, "heart.png"), width=0.5*inch, height=0.5*inch) if day % 3 == 0 else ""
week_table_data.append([
Paragraph(str(day), styles['TableCell']),
Paragraph("Follow your meal plan", styles['TableCell']),
Paragraph(workout_schedule[day - 1], styles['TableCell']),
"", # space for checkmark
sticker
])
week_table = Table(week_table_data, colWidths=[1*cm, 5*cm, 5*cm, 2*cm, 2*cm], repeatRows=1)
week_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#FF85A2")), # Header background
("TEXTCOLOR", (0,0), (-1,0), colors.white), # Header text color
("ALIGN", (0,0), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("FONTNAME", (0,0), (-1,0), font_header),
("FONTNAME", (0,1), (-1,-1), font_body),
("FONTSIZE", (0,0), (-1,-1), 10),
("BOX", (0,0), (-1,-1), 1, colors.HexColor("#FF85A2")),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#FFB6C1")),
("BACKGROUND", (0,1), (-1,-1), colors.HexColor("#FFECF1")),
]))
elements.append(week_table)
elements.append(Spacer(1, 15))
# Progress tracking section
progress_title = Table([[Paragraph("Progress Tracking", styles['WeekTitle'])]], colWidths=[doc.width])
elements.append(progress_title)
progress_table = Table([
["Week", "Weight", "Measurements", "Energy Level", "Sticker Reward"],
["Start", "", "", "", Image(os.path.join(sticker_dir, "star.png"), width=0.7*inch, height=0.7*inch)],
["Week 2", "", "", "", Image(os.path.join(sticker_dir, "flower.png"), width=0.7*inch, height=0.7*inch)],
["Week 4", "", "", "", Image(os.path.join(sticker_dir, "heart.png"), width=0.7*inch, height=0.7*inch)],
["Week 6", "", "", "", Image(os.path.join(sticker_dir, "star.png"), width=0.7*inch, height=0.7*inch)],
["Week 8", "", "", "", Image(os.path.join(sticker_dir, "flower.png"), width=0.7*inch, height=0.7*inch)]
], colWidths=[2*cm, 4*cm, 4*cm, 3*cm, 3*cm])
progress_table.setStyle(TableStyle([
("BACKGROUND", (0,0), (-1,0), colors.HexColor("#FF85A2")),
("TEXTCOLOR", (0,0), (-1,0), colors.white),
("FONTNAME", (0,0), (-1,0), font_header),
("FONTSIZE", (0,0), (-1,0), 12),
("BACKGROUND", (0,1), (-1,-1), colors.HexColor("#FFECF1")),
("GRID", (0,0), (-1,-1), 0.5, colors.HexColor("#FFB6C1")),
("ALIGN", (0,0), (-1,-1), "CENTER"),
("VALIGN", (0,0), (-1,-1), "MIDDLE"),
("BOX", (0,0), (-1,-1), 1, colors.HexColor("#FF85A2")),
]))
elements.append(progress_table)
elements.append(Spacer(1, 20))
# Notes section
notes_title = Table([[Paragraph("Personal Notes & Achievements", styles['WeekTitle'])]], colWidths=[doc.width])
elements.append(notes_title)
notes_table = Table([
[Paragraph(
"Celebrate your wins here! ✨
"
"Week 1: ________________________________________________
"
"Week 2: ________________________________________________
"
"Week 3: ________________________________________________
"
"Week 4: ________________________________________________
"
"Week 5: ________________________________________________
"
"Week 6: ________________________________________________
"
"Week 7: ________________________________________________
"
"Week 8: ________________________________________________",
styles['Body'])
]
], colWidths