Skip to content

Commit 1612f35

Browse files
committed
разделение ui на отдельные модули
1 parent 542379e commit 1612f35

File tree

5 files changed

+189
-0
lines changed

5 files changed

+189
-0
lines changed

src/js/ui/UIStateManager.js

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import i18next from "../i18n.js";
2+
import { renderErrors, renderSuccess } from "./renderForm.js";
3+
import { renderFeedsPending } from "./renderFeeds.js";
4+
const title = document.querySelector("#main-title");
5+
const subtitle = document.querySelector("#subtitle");
6+
const input = document.querySelector("#url-input");
7+
const label = document.querySelector("#url-label");
8+
const addBtn = document.querySelector("#add-feed-btn");
9+
const example = document.querySelector("#example");
10+
const feedback = document.querySelector("#feedback");
11+
const fullBtn = document.querySelector("#btn-full");
12+
const closeBtn = document.querySelector("#btn-close");
13+
14+
export const renderUIText = () => {
15+
title.textContent = i18next.t("title");
16+
subtitle.textContent = i18next.t("subtitle");
17+
input.placeholder = i18next.t("form_placeholder");
18+
label.textContent = i18next.t("form_placeholder");
19+
addBtn.textContent = i18next.t("add_btn");
20+
fullBtn.textContent = i18next.t("full_btn");
21+
closeBtn.textContent = i18next.t("close_btn");
22+
example.textContent = i18next.t("example");
23+
};
24+
25+
const cleanDomElements = () => {
26+
input.classList.remove("is-invalid");
27+
feedback.classList.remove("text-danger");
28+
feedback.classList.remove("text-success");
29+
feedback.textContent = "";
30+
const spinner = document.querySelector(".spinner-container");
31+
if (spinner) spinner.remove();
32+
};
33+
34+
export const renderUi = (uiState, message) => {
35+
switch (uiState) {
36+
case "error":
37+
cleanDomElements();
38+
renderErrors(message);
39+
break;
40+
case "success":
41+
cleanDomElements();
42+
renderSuccess();
43+
break;
44+
case "pending":
45+
cleanDomElements();
46+
renderFeedsPending();
47+
break;
48+
case "update":
49+
// нужен ли отдельный case?
50+
break;
51+
default:
52+
cleanDomElements();
53+
break;
54+
}
55+
};

src/js/ui/renderFeeds.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import i18next from "../../i18n.js";
2+
export const renderFeeds = (feeds) => {
3+
const feedsContainer = document.querySelector(".feeds");
4+
5+
feedsContainer.innerHTML = `
6+
<div class="card border-0">
7+
<div class="card-body">
8+
<h2 class="card-title h4">${i18next.t("feeds")}</h2>
9+
</div>
10+
<ul class="list-group border-0 rounded-0">
11+
${feeds
12+
.map(
13+
(feed) => `
14+
<li class="list-group-item border-0 border-end-0">
15+
<h3 class="h6 m-0">${feed.title}</h3>
16+
<p class="m-0 small text-black-50">${feed.description}</p>
17+
</li>
18+
`
19+
)
20+
.join("")}
21+
</ul>
22+
</div>
23+
`;
24+
};
25+
26+
export const renderFeedsPending = () => {
27+
const postsContainer = document.querySelector(".feeds");
28+
const spinner = document.createElement("div");
29+
spinner.classList.add("spinner-container");
30+
spinner.innerHTML = `
31+
<div
32+
id="posts-spinner"
33+
class="spinner-border text-primary d-none"
34+
role="status">
35+
<span>${i18next.t("ui.pending")}</span>
36+
</div>
37+
`;
38+
postsContainer.append(spinner);
39+
};

src/js/ui/renderForm.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import i18next from "../i18n.js";
2+
const input = document.querySelector("#url-input");
3+
const feedback = document.querySelector("#feedback");
4+
5+
export const renderInputValue = (value) => {
6+
input.value = value;
7+
};
8+
9+
export const renderErrors = (error) => {
10+
input.classList.add("is-invalid");
11+
feedback.classList.add("text-danger");
12+
feedback.textContent = i18next.t(`errors.${error}`);
13+
};
14+
15+
export const renderSuccess = () => {
16+
feedback.classList.add("text-success");
17+
feedback.textContent = i18next.t(`ui.success`);
18+
};
19+

src/js/ui/renderModal.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
export const showModal = (item) => {
2+
const modal = document.querySelector("#modal");
3+
modal.classList.add("d-block", "show");
4+
modal.setAttribute("aria-hidden", true);
5+
6+
const modalTitle = modal.querySelector(".modal-title");
7+
const modalText = modal.querySelector(".modal-body");
8+
9+
modalTitle.textContent = item.title;
10+
modalText.textContent = item.description;
11+
modal.querySelector("a").href = item.link;
12+
13+
const backdrop = document.createElement("div");
14+
backdrop.classList.add("modal-backdrop", "fade", "show");
15+
modal.before(backdrop);
16+
};
17+
18+
export const closeModal = () => {
19+
const modal = document.querySelector("#modal");
20+
modal.classList.remove("d-block", "show");
21+
modal.setAttribute("aria-hidden", false);
22+
23+
const modalTitle = modal.querySelector(".modal-title");
24+
const modalText = modal.querySelector(".modal-body");
25+
26+
modalTitle.textContent = "";
27+
modalText.textContent = "";
28+
modal.querySelector("a").href = "#";
29+
30+
document.querySelector(".modal-backdrop").remove();
31+
};
32+

src/js/ui/renderPosts.js

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import i18next from "../../i18n.js";
2+
export const renderPosts = (posts) => {
3+
const postsContainer = document.querySelector(".posts");
4+
5+
postsContainer.innerHTML = `
6+
<div class="card border-0">
7+
<div class="card-body">
8+
<h2 class="card-title h4">${i18next.t("posts")}</h2>
9+
</div>
10+
<ul class="list-group border-0 rounded-0">
11+
${posts
12+
.map((post) => {
13+
const titleStyle = post.viewed ? "fw-normal" : "fw-bold";
14+
return `
15+
<li class="list-group-item d-flex justify-content-between align-items-start border-0 border-end-0">
16+
<a href="${post.link}" class=${titleStyle} data-id="${post.id}" target="_blank" rel="noopener noreferrer">${post.title}</a>
17+
<button type="button" class="btn btn-outline-primary btn-sm modal-btn" data-id="${post.id}" data-bs-toggle="modal" data-bs-target="#modal">${i18next.t("preview")}</button>
18+
</li>
19+
`;
20+
})
21+
.join("")}
22+
</ul>
23+
</div>
24+
`;
25+
};
26+
27+
export const renderPostsPending = () => {
28+
const postsContainer = document.querySelector(".posts");
29+
postsContainer.innerHTML = `
30+
<div
31+
id="posts-spinner"
32+
class="spinner-border text-primary d-none"
33+
role="status">
34+
<span>Загрузка постов...</span>
35+
</div>
36+
`;
37+
};
38+
39+
export const renderViewedPost = (id) => {
40+
const viewedPost = document.querySelector(`[data-id="${id}"]`);
41+
viewedPost.classList.remove("fw-bold");
42+
viewedPost.classList.add("fw-normal");
43+
};
44+

0 commit comments

Comments
 (0)