Export result to txt/docx

This commit is contained in:
2026-01-13 21:08:24 +02:00
parent e9ca378099
commit 4b49b4b54e
6 changed files with 265 additions and 25 deletions

View File

@@ -1,21 +1,18 @@
// here lies the logic for the export of the final schedule into docx/pdf formats
use std::{fs::File, io::Write};
use docx_rs::{Docx, Paragraph, Run, RunFonts, Table, TableCell, TableRow};
use log::info;
use crate::{
config::UserConfig,
schedule::MonthlySchedule,
slot::{month_to_greek, weekday_to_greek, Day, ShiftPosition, Slot},
};
#[derive(Debug)]
pub enum FileType {
Txt,
Json,
Csv,
Doc,
Pdf,
Docx,
}
pub trait Export {
@@ -26,10 +23,7 @@ impl Export for MonthlySchedule {
fn export(&self, file_type: FileType, config: &UserConfig) {
match file_type {
FileType::Txt => self.export_as_txt(config),
FileType::Csv => self.export_as_csv(config),
FileType::Json => self.export_as_json(config),
FileType::Doc => self.export_as_doc(config),
FileType::Pdf => self.export_as_pdf(config),
FileType::Docx => self.export_as_doc(config),
};
// TODO: make this env var from a config file? Option to change this in-app
@@ -49,32 +43,155 @@ impl MonthlySchedule {
.write_all(self.pretty_print(config).as_bytes())
.expect("Failed to write to buffer");
writer
.write_all(self.report(config).as_bytes())
.expect("Failed to write to buffer");
writer.flush().expect("Failed to flush buffer");
info!("im here");
"ok".to_string()
}
pub fn export_as_csv(&self, config: &UserConfig) -> String {
todo!()
}
pub fn export_as_json(&self, config: &UserConfig) -> String {
todo!()
}
pub fn export_as_doc(&self, config: &UserConfig) -> String {
todo!()
}
let path = std::path::Path::new("./schedule.docx");
let file = std::fs::File::create(path).unwrap();
pub fn export_as_pdf(&self, config: &UserConfig) -> String {
todo!()
let header = Table::new(vec![
TableRow::new(vec![TableCell::new().add_paragraph(
Paragraph::new()
.add_run(Run::new().bold().add_text("Εφημερίες Ακτινολογικό"))
.fonts(RunFonts::new().ascii("Arial")),
)]),
TableRow::new(vec![TableCell::new().add_paragraph(
Paragraph::new()
.add_run(Run::new().bold().add_text(format!(
"Μήνας {} {}",
month_to_greek(config.month.number_from_month()),
config.year
)))
.fonts(RunFonts::new().ascii("Arial")),
)]),
TableRow::new(vec![TableCell::new().add_paragraph(
Paragraph::new()
.add_run(Run::new().bold().add_text(""))
.fonts(RunFonts::new().ascii("Arial")),
)]),
TableRow::new(vec![TableCell::new().add_paragraph(
Paragraph::new()
.add_run(
Run::new()
.bold()
.add_text("ΠΑΝΕΠΙΣΤΗΜΙΑΚΟ ΓΕΝΙΚΟ ΝΟΣΟΚΟΜΕΙΟ ΙΩΑΝΝΙΝΩΝ"),
)
.fonts(RunFonts::new().ascii("Arial")),
)]),
]);
let mut doc = Docx::new().add_table(header);
let mut residents_table = Table::new(vec![]);
for d in 1..=config.total_days() {
let day = Day(d);
let is_weekend = day.is_weekend(config.month.number_from_month(), config.year);
let slot_first = Slot::new(Day(d), ShiftPosition::First);
let slot_first_res_id = self.get_resident_id(&slot_first);
let res_name_1 = config
.residents
.iter()
.find(|r| Some(&r.id) == slot_first_res_id)
.map(|r| r.name.as_str())
.unwrap();
let res_name_2 = if day.is_open_shift() {
let slot_second = Slot::new(Day(d), ShiftPosition::Second);
let slot_second_res_id = self.get_resident_id(&slot_second);
config
.residents
.iter()
.find(|r| Some(&r.id) == slot_second_res_id)
.map(|r| r.name.as_str())
} else {
None
};
let make_run = |text: &str| {
let mut run = Run::new().add_text(text);
if is_weekend {
run = run.bold();
}
run
};
let residents_table_row = TableRow::new(vec![
TableCell::new().add_paragraph(
Paragraph::new()
.add_run(make_run(&format!("{d}")))
.fonts(RunFonts::new().ascii("Arial")),
),
TableCell::new().add_paragraph(
Paragraph::new()
.add_run(make_run(weekday_to_greek(
Day(d).weekday(config.month.number_from_month(), config.year),
)))
.fonts(RunFonts::new().ascii("Arial")),
),
TableCell::new().add_paragraph(
Paragraph::new()
.add_run(make_run(res_name_1))
.fonts(RunFonts::new().ascii("Arial")),
),
TableCell::new().add_paragraph(
Paragraph::new()
.add_run(make_run(res_name_2.unwrap_or("")))
.fonts(RunFonts::new().ascii("Arial")),
),
]);
residents_table = residents_table.add_row(residents_table_row);
}
doc = doc.add_table(residents_table);
doc.build().pack(file).unwrap();
"just a string".to_string()
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;
use rstest::{fixture, rstest};
use crate::{
config::UserConfig, generator::backtracking, resident::Resident, schedule::MonthlySchedule,
slot::Slot,
};
#[fixture]
fn schedule() -> MonthlySchedule {
MonthlySchedule::new()
}
#[fixture]
fn config() -> UserConfig {
let mut config = UserConfig::default().with_residents(vec![
Resident::new("1", "Στέφανος"),
Resident::new("2", "Ιορδάνης"),
Resident::new("3", "Μαρία"),
Resident::new("4", "Βεατρίκη"),
Resident::new("5", "Τάκης"),
Resident::new("6", "Μάκης"),
]);
config.calculate_workload_limits();
config.calculate_holiday_limits();
config.calculate_shift_type_fairness();
config
}
#[rstest]
pub fn xxxy() {}
pub fn test_export_as_doc(mut schedule: MonthlySchedule, config: UserConfig) {
backtracking(&mut schedule, Slot::default(), &config);
schedule.export_as_doc(&config);
}
}

View File

@@ -50,7 +50,7 @@ fn generate(config: UserConfigDTO, state: tauri::State<'_, AppState>) -> Monthly
fn export(config: UserConfigDTO, state: tauri::State<'_, AppState>) {
let config = UserConfig::from_dto(config);
let schedule = state.schedule.lock().unwrap();
schedule.export(FileType::Txt, &config);
schedule.export(FileType::Docx, &config);
}
#[cfg_attr(mobile, tauri::mobile_entry_point)]

View File

@@ -128,6 +128,36 @@ pub enum ShiftPosition {
Second,
}
pub fn weekday_to_greek(weekday: Weekday) -> &'static str {
match weekday {
Weekday::Mon => "Δευτέρα",
Weekday::Tue => "Τρίτη",
Weekday::Wed => "Τετάρτη",
Weekday::Thu => "Πέμπτη",
Weekday::Fri => "Παρασκευή",
Weekday::Sat => "Σάββατο",
Weekday::Sun => "Κυριακή",
}
}
pub fn month_to_greek(month: u32) -> &'static str {
match month {
1 => "Ιανουάριος",
2 => "Φεβρουάριος",
3 => "Μάρτιος",
4 => "Απρίλιος",
5 => "Μάιος",
6 => "Ιούνιος",
7 => "Ιούλιος",
8 => "Αύγουστος",
9 => "Σεπτέμβριος",
10 => "Οκτώβριος",
11 => "Νοέμβριος",
12 => "Δεκέμβριος",
_ => panic!("Unable to find translation for month {}", month),
}
}
#[cfg(test)]
mod tests {
use rstest::rstest;