Skip to content

HW 5#4

Open
matiko-ma wants to merge 8 commits intomainfrom
hw_5
Open

HW 5#4
matiko-ma wants to merge 8 commits intomainfrom
hw_5

Conversation

@matiko-ma
Copy link
Copy Markdown
Owner

@matiko-ma matiko-ma commented Dec 2, 2025

Изменения

  • Добавлена интеграция API timeapi.io для отображения даты и времени на момент генерации резюме (GET-запрос)
  • Добавлена интеграция API html2pdf.app для генерации PDF (POST-запрос)

Отмечу, что оба API добавлены только ради выполнения данного ДЗ, в итоговом проекте их не будет.

Если с timeapi.io все в целом очевидно, то html2pdf.app мне не подходит по ряду причин. Во-первых, он платный, там, конечно, дается 100 бесплатных кредитов в месяц, но в долгосрочной перспективе этого мало. Во-вторых, на бесплатном тарифе есть ограничение размера файла 1 MB, что достаточно мало, особенно если учитывать загружаемые профессиональные фото. В-третьих, он не учитывает CSS-надстройки, особенно что касается кастомных шрифтов. Да и в целом, как показала практика, использовать иностранные API в российских реалиях - не самый практичный способ.

Я планирую реализовать этот функционал через библиотеку, но, насколько я смогла на данный момент выяснить, наиболее подходящие мне библиотеки требуют развертывания на сервере, а я пока не имею представления, как это сделать.

To be done

  • Доработать текстовое наполнение сайта
  • Сверстать финальный шаблон резюме
  • Добавить функцию генерации PDF

@lyaplyap
Copy link
Copy Markdown

lyaplyap commented Dec 5, 2025

Ревью дз по API

Общие комментарии

  • Работу с API лучше было бы вынести в отдельные функции (и вообще в идеале — в отдельный файл), так улучшится читаемость кода, станет понятно, за что отвечает та или иная функциональность, и не будут смешиваться логика получения данных и логика отрисовки UI
  • Для POST-запроса мы храним apiKey прямо в коде — для дз это окей, но вообще в реальных проектах ключи и другую чувствительную информацию нельзя хранить прямо в клиентском коде (потому что пользователь де-факто видит весь это код и может увести наш ключ)
  • Методы для работы с API не обёрнуты в try/catch и никак не обрабатывают возможные ошибки. Опять-таки для учебного проекта — это ок, но в реальных приложениях сервера падают (и довольно часто), и нужно быть к этому готовыми с точки зрения клиентской логики и UI :)
  • На лекции говорили вот про эту библиотеку для работы с PDF, можно попробовать использовать её

Соответствие критериям

  • Есть ссылка на код проекта с подключенным API [ok]
  • Есть функция, получающая данные с сервера (GET) [ok]
  • Есть функция, отправляющие данные на сервер (POST/PUT/PATCH) [ok]
  • Полученные данные используются / показываются на странице [ok]

Итого: 9

@matiko-ma
Copy link
Copy Markdown
Owner Author

  • Для POST-запроса мы храним apiKey прямо в коде — для дз это окей, но вообще в реальных проектах ключи и другую чувствительную информацию нельзя хранить прямо в клиентском коде (потому что пользователь де-факто видит весь это код и может увести наш ключ)

А как apiKey прятать, если все наши файлики заведомо видны браузеру..?

  • На лекции говорили вот про эту библиотеку для работы с PDF, можно попробовать использовать её

Я вот вроде прочитала всю документацию, но там везде говорится только о функции просмотра готового PDF-файла. Может, я куда-то не туда смотрю..?

@emworks
Copy link
Copy Markdown

emworks commented Dec 18, 2025

Я вот вроде прочитала всю документацию, но там везде говорится только о функции просмотра готового PDF-файла. Может, я куда-то не туда смотрю..?

Это я перепутал, pdf.js не подойдёт. Наверное, у меня что-то другое было, забыл уже (

Попробуй использовать html2pdf. Я посмотрел твой код и накидал небольшой пример, который может помочь :)

<button onclick="downloadPdf()">Generate!</button>

<!-- для создания pdf из html используется библиотека html2pdf https://ekoopmans.github.io/html2pdf.js/#cdn -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"
        integrity="sha512-GsLlZN/3F2ErC5ifS5QtgpiJtWd43JWSuIgh7mbzZ8zBps+dvLusV+eNQATqgA/HdeKFVgA5v3S/cIrLF7QnIg=="
        crossorigin="anonymous" referrerpolicy="no-referrer"></script>

<script>
  function generateHTML() {
    return '\n        <html>\n        <head>\n            <meta charset="UTF-8" />\n            <style>\n          h1 { color: green; }      .section { margin-bottom: 20px; }\n                img.photo {\n                    width:150px; height:150px; border-radius:50%; object-fit:cover;\n                }\n            </style>\n        </head>\n        <body>\n            <p><b>Создано:</b> 1766074436192 МСК</p>\n            <h1>tetst sr</h1>\n            \n\n            <p><b>Должность:</b> test</p>\n            <p><b>Email:</b> t@t.com</p>\n            <p><b>Телефон:</b> 42552345</p>\n\n            <div class="section">\n                <div class="title">О себе</div>\n                <p></p>\n            </div>\n\n            <div class="section"><div class="title">Образование</div><div><p><span>Уровень образования:</span> lf</p><p><span>Учебное заведение:</span> sdf</p><p><span>Начало обучения:</span> 2025-11</p><p><span>Окончание обучения:</span> 2025-07</p><p><span>Факультет:</span> fd</p><p><span>Специализация:</span> dsf</p></div></div>\n\n        <div class="section"><div class="title">Опыт работы</div><div><p><span>Должность:</span> fdsa</p><p><span>Организация:</span> fds</p><p><span>Начало работы:</span> 2025-12</p><p><span>Работаю сейчас:</span> on</p><p><span>Обязанности и достижения:</span> </p></div></div>\n\n        \n\n        \n\n        \n\n        \n\n        </body>\n        </html>'
  }
  
  function downloadPdf() {
    // как видно из документации html2pdf, библиотека делает pdf из DOM-элемента
    // если элемент есть на странице – можно взять его, например, через document.querySelector*
    // но можно и просто создать любой DOM-элемент, например, <div>
    const element = document.createElement('div');
    // и записать в innerHTML элемента строку с html –
    // element сам отрендерит из этой строки html
    // generateHTML() как раз возращает такую строку
    element.innerHTML = generateHTML();
    // и вот такой element уже можно сразу отправить в html2pdf,
    // даже не добавляя его на страницу
    const worker = html2pdf().from(element);
    // и скачать – видно, что CSS-стили также применились
    worker.save();    
  }
</script>

Для проверки можно сохранить этот код как html-файл (можно прям так скопировать в файл и больше ничего там не писать) и открыть в браузере.

@malmarie21
Copy link
Copy Markdown

Читаемость и понятность кода
Код структурирован логично: разделены функции генерации HTML (generateHTML, renderSection) и обработка событий DOM. Асинхронные операции с API реализованы понятно, переменные имеют говорящие имена, что облегчает чтение и понимание логики

Отсутствие ошибок
Ошибок не обнаружено. Асинхронные запросы корректно обернуты в await, JSON корректно парсится, проверки на существование данных выполнены. Потенциальные ошибки (например, отсутствие данных в sessionStorage) учитываются

Модульность и переиспользуемость кода
Код разделён на логические блоки: функции для генерации HTML, отдельные обработчики форм и кнопок, генерация PDF через API вынесена отдельно. Это облегчает расширение проекта и переиспользование компонентов

Соответствие стандартам форматирования и кодирования
Форматирование единообразное, отступы соблюдены, имена переменных и функций читаемы и описательны. Используется современный синтаксис ES6, стрелочные функции и const/let

Соответствие требованиям задания
Проект использует API: GET-запрос к timeapi.io для получения текущего времени; POST-запрос к html2pdf.app для генерации PDF. Полученные данные используются на странице: отображается дата, создаётся PDF с введённой информацией. Основные сценарии работы с API реализованы, ошибки при запросах корректно обрабатываются

@lyaplyap
Copy link
Copy Markdown

  • Для POST-запроса мы храним apiKey прямо в коде — для дз это окей, но вообще в реальных проектах ключи и другую чувствительную информацию нельзя хранить прямо в клиентском коде (потому что пользователь де-факто видит весь это код и может увести наш ключ)

А как apiKey прятать, если все наши файлики заведомо видны браузеру..?

Для этого нужен бэкенд — некоторый удалённый защищённый сервер. Ключ будет храниться там и с этим ключом он будет ходить в нужное API сам, а сам будет предоставлять вашему фронтенду собственное API, которое делает нужные операции, но для которого не нужен этот самый ключ (в том числе для такого, например, используются прокси-серверы)

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.

4 participants