Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
3 changes: 1 addition & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1 @@
.DS_Store
node_modules
node_modules/
10 changes: 8 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,14 @@ https::

## Первоначальная оценка

ХХХХ часов
1000 часов

## Фактически затраченное время

YYYY часов
1001 hours






99 changes: 95 additions & 4 deletions api.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
// Замени на свой, чтобы получить независимый от других набор данных.
// "боевая" версия инстапро лежит в ключе prod
const personalKey = "prod";
const personalKey = "DmitriiTheBest";
const baseHost = "https://webdev-hw-api.vercel.app";
const postsHost = `${baseHost}/api/v1/${personalKey}/instapro`;

// функция getPosts делает запросы к API на получение постов
export function getPosts({ token }) {
return fetch(postsHost, {
method: "GET",
Expand All @@ -13,7 +14,7 @@ export function getPosts({ token }) {
})
.then((response) => {
if (response.status === 401) {
throw new Error("Нет авторизации");
throw new Error("No authorization");
}

return response.json();
Expand All @@ -23,6 +24,7 @@ export function getPosts({ token }) {
});
}

// функция registerUser делает запросы на регистрацию
// https://github.com/GlebkaF/webdev-hw-api/blob/main/pages/api/user/README.md#%D0%B0%D0%B2%D1%82%D0%BE%D1%80%D0%B8%D0%B7%D0%BE%D0%B2%D0%B0%D1%82%D1%8C%D1%81%D1%8F
export function registerUser({ login, password, name, imageUrl }) {
return fetch(baseHost + "/api/user", {
Expand All @@ -35,12 +37,13 @@ export function registerUser({ login, password, name, imageUrl }) {
}),
}).then((response) => {
if (response.status === 400) {
throw new Error("Такой пользователь уже существует");
throw new Error("Such user already exists");
}
return response.json();
});
}

// функция loginUser делает запросы на логин
export function loginUser({ login, password }) {
return fetch(baseHost + "/api/user/login", {
method: "POST",
Expand All @@ -50,12 +53,13 @@ export function loginUser({ login, password }) {
}),
}).then((response) => {
if (response.status === 400) {
throw new Error("Неверный логин или пароль");
throw new Error("Login or password is incorrect");
}
return response.json();
});
}

// функция uploadImage делает запросы на загрузку картинки в облако
// Загружает картинку в облако, возвращает url загруженной картинки
export function uploadImage({ file }) {
const data = new FormData();
Expand All @@ -68,3 +72,90 @@ export function uploadImage({ file }) {
return response.json();
});
}

// # написать функцию для отправления новых данных
export const postPosts = ({ token, description, imageUrl }) => {
return fetch(postsHost, {
method: "POST",
body: JSON.stringify({
description,
imageUrl,
}),
headers: {
Authorization: token,
},
}).then((response) => {
if (response.status === 500) {
throw new Error("Server is broken");
} else if (response.status === 400) {
throw new Error("Bad request");
} else {
return response.json();
}
});
};

// # написать функцию для удаления поста
export const deletePost = (id, { token }) => {
return fetch(`${postsHost}/${id}`, {
method: "DELETE",
headers: {
Authorization: token,
},
}).then((response) => {
return response.json();
});
};

// # получаем посты конкретного пользователя (юзера)
export const fetchPostsUser = ({id, token }) => {
return fetch(`${postsHost}/user-posts/${id}`, {
method: "GET",
headers: {
Authorization: token,
},
})
.then((response) => {
if (response.status === 401) {
throw new Error("Нет авторизации");
}

return response.json();
})
.then((data) => {
return data.posts;
});
};

// # adding likes
export const addLike = (id, { token }) => {
return fetch(`${postsHost}/${id}/like`, {
method: "POST",
headers: {
Authorization: token,
},
}).then((response) => {
if (response.status === 200) {
return response.json();
}
throw new Error("Only authorized users can add likes");
});
};

// # removing likes
export const removeLike = (id, { token }) => {
return fetch(`${postsHost}/${id}/dislike`, {
method: "DELETE",
// method: "POST",
headers: {
Authorization: token,
},
}).then((response) => {
if (response.status === 200) {
return response.json();
}
throw new Error("Only authorized users can remove likes");
});
};

// API is ready
50 changes: 45 additions & 5 deletions components/add-post-page-component.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,62 @@
import { renderHeaderComponent } from "./header-component.js";
import { renderUploadImageComponent } from "./upload-image-component.js";

let imageUrl = "";

export function renderAddPostPageComponent({ appEl, onAddPostClick }) {
const render = () => {
// TODO: Реализовать страницу добавления поста
const appHtml = `
<div class="page-container">
<div class="header-container"></div>
Cтраница добавления поста
<button class="button" id="add-button">Добавить</button>

<div class="add-form">
<h2 class="add-form__title">Add a new post</h2>
<div class="upload-image-container"></div>

<label>
Describe a photo:
<br>
<textarea class="add-form__text" type="textarea" rows="7"></textarea>
</label>

<button class="button" id="add-button">Add</button></div>

</div>
`;

appEl.innerHTML = appHtml;

renderHeaderComponent({
element: document.querySelector(".header-container"),
});

renderUploadImageComponent({
element: appEl.querySelector(".upload-image-container"),
onImageUrlChange(newImageUrl) {
imageUrl = newImageUrl;
},
});

document.getElementById("add-button").addEventListener("click", () => {
if (!imageUrl) {
alert("Choose an image, please!");
return;
}
if (!(document.querySelector(".add-form__text").value)) {
alert("Photo description is not completed!");
return;
}

onAddPostClick({
description: "Описание картинки",
imageUrl: "https://image.png",
description: document.querySelector(".add-form__text").value
.replaceAll("&", "&amp;")
.replaceAll("<", "&lt;")
.replaceAll(">", "&gt;")
.replaceAll('"', "&quot;"),
imageUrl: imageUrl,
});
});
});
};

render();
Expand Down
36 changes: 22 additions & 14 deletions components/auth-page-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,26 +24,26 @@ export function renderAuthPageComponent({ appEl, setUser }) {
!isLoginMode
? `
<div class="upload-image-container"></div>
<input type="text" id="name-input" class="input" placeholder="Имя" />
<input type="text" id="name-input" class="input" placeholder="Name" />
`
: ""
}

<input type="text" id="login-input" class="input" placeholder="Логин" />
<input type="password" id="password-input" class="input" placeholder="Пароль" />
<input type="text" id="login-input" class="input" placeholder="Username" />
<input type="password" id="password-input" class="input" placeholder="Password" />

<div class="form-error"></div>

<button class="button" id="login-button">${
isLoginMode ? "Войти" : "Зарегистрироваться"
isLoginMode ? "Sign in" : "Sign up"
}</button>
</div>

<div class="form-footer">
<p class="form-footer-title">
${isLoginMode ? "Нет аккаунта?" : "Уже есть аккаунт?"}
${isLoginMode ? "Haven't got an account yet?" : "Have got an account?"}
<button class="link-button" id="toggle-button">
${isLoginMode ? "Зарегистрироваться." : "Войти."}
${isLoginMode ? "Sign up." : "Sign in."}
</button>
</p>

Expand All @@ -60,14 +60,19 @@ export function renderAuthPageComponent({ appEl, setUser }) {
appEl.querySelector(".form-error").textContent = message;
};

renderHeaderComponent({
// в renderHeaderComponent передаем элемент,
// в этот элемент отрендерит какой-то кусок разметки и
// навесит на этот кусок обработчики событий
renderHeaderComponent({ // рендер шапки с логотипом и кнопкой входа и регистрации
element: document.querySelector(".header-container"),
});

const uploadImageContainer = appEl.querySelector(".upload-image-container");

if (uploadImageContainer) {
renderUploadImageComponent({
renderUploadImageComponent({ // рендер компонента выбора изображения
// в качестве аргумента передаем элемент, в котором будет отрендерен компонент
// и функцию, которая будет вызвана при изменении изображения
element: appEl.querySelector(".upload-image-container"),
onImageUrlChange(newImageUrl) {
imageUrl = newImageUrl;
Expand All @@ -83,12 +88,12 @@ export function renderAuthPageComponent({ appEl, setUser }) {
const password = document.getElementById("password-input").value;

if (!login) {
alert("Введите логин");
alert("Enter your username");
return;
}

if (!password) {
alert("Введите пароль");
alert("Enter your password");
return;
}

Expand All @@ -108,21 +113,21 @@ export function renderAuthPageComponent({ appEl, setUser }) {
const name = document.getElementById("name-input").value;
const password = document.getElementById("password-input").value;
if (!name) {
alert("Введите имя");
alert("Enter your name");
return;
}
if (!login) {
alert("Введите логин");
alert("Enter your username");
return;
}

if (!password) {
alert("Введите пароль");
alert("Enter your password");
return;
}

if (!imageUrl) {
alert("Не выбрана фотография");
alert("Photo is not selected");
return;
}

Expand Down Expand Up @@ -150,3 +155,6 @@ export function renderAuthPageComponent({ appEl, setUser }) {

renderForm();
}


// done
11 changes: 7 additions & 4 deletions components/header-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,16 @@ export function renderHeaderComponent({ element }) {
<button class="header-button add-or-login-button">
${
user
? `<div title="Добавить пост" class="add-post-sign"></div>`
: "Войти"
? `<div title="Add a post" class="add-post-sign"></div>`
: "Sign in"
}
</button>
${
user
? `<button title="${user.name}" class="header-button logout-button">Выйти</button>`
? `<button title="${user.name}" class="header-button logout-button">Sign out</button>`
: ""
}
}
</button>
</div>

`;
Expand All @@ -39,3 +40,5 @@ export function renderHeaderComponent({ element }) {

return element;
}

// done
2 changes: 2 additions & 0 deletions components/loading-page-component.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,5 @@ export function renderLoadingPageComponent({ appEl, user, goToPage }) {
goToPage,
});
}

// done
Loading