похороните меня за плинтусом
This commit is contained in:
9
db.json
9
db.json
@@ -44,15 +44,6 @@
|
||||
"image": "img/lacoste.jpg",
|
||||
"category": "1",
|
||||
"condition": "1"
|
||||
},
|
||||
{
|
||||
"id": "1748083467760",
|
||||
"name": "sdf",
|
||||
"price": 3,
|
||||
"description": "sdfsf",
|
||||
"image": "https://i.pinimg.com/736x/a5/53/a4/a553a49e31faaa36b7960a280a5dca4a.jpg",
|
||||
"category": "1",
|
||||
"condition": "1"
|
||||
}
|
||||
],
|
||||
"category": [
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
class ApiService {
|
||||
constructor(baseUrl) {
|
||||
this.baseUrl = baseUrl;
|
||||
}
|
||||
|
||||
async get(endpoint) {
|
||||
const response = await fetch(`${this.baseUrl}/${endpoint}`);
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
async post(endpoint, data) {
|
||||
const response = await fetch(`${this.baseUrl}/${endpoint}`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
async put(endpoint, id, data) {
|
||||
const response = await fetch(`${this.baseUrl}/${endpoint}/${id}`, {
|
||||
method: 'PUT',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
async delete(endpoint, id) {
|
||||
const response = await fetch(`${this.baseUrl}/${endpoint}/${id}`, {
|
||||
method: 'DELETE',
|
||||
});
|
||||
return await response.json();
|
||||
}
|
||||
}
|
||||
|
||||
export const apiService = new ApiService('http://localhost:3000');
|
||||
@@ -1,38 +0,0 @@
|
||||
import { BasketModel } from './model.js';
|
||||
import { BasketView } from './view.js';
|
||||
|
||||
export class BasketController {
|
||||
constructor() {
|
||||
this.model = new BasketModel();
|
||||
this.view = new BasketView();
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.view.bindAddToBasket(this.handleBasketAction.bind(this));
|
||||
this.updateBasketButtons();
|
||||
}
|
||||
|
||||
async handleBasketAction(productId, action) {
|
||||
const product = await this.getProductById(productId);
|
||||
|
||||
if (action === 'add') {
|
||||
await this.model.addToBasket(product);
|
||||
} else {
|
||||
await this.model.removeFromBasket(productId);
|
||||
}
|
||||
}
|
||||
|
||||
async getProductById(id) {
|
||||
const response = await fetch(`http://localhost:3000/shmots/${id}`);
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
async updateBasketButtons() {
|
||||
const items = await this.model.getBasketItems();
|
||||
items.forEach(item => {
|
||||
this.view.updateBasketButton(item.id, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { apiService } from '../ApiService.js';
|
||||
|
||||
export class BasketModel {
|
||||
async getBasketItems() {
|
||||
return await apiService.get('basket');
|
||||
}
|
||||
|
||||
async addToBasket(product) {
|
||||
return await apiService.post('basket', product);
|
||||
}
|
||||
|
||||
async removeFromBasket(id) {
|
||||
return await apiService.delete('basket', id);
|
||||
}
|
||||
|
||||
async isInBasket(productId) {
|
||||
const items = await this.getBasketItems();
|
||||
return items.some(item => item.id === productId);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
export class BasketView {
|
||||
constructor() {
|
||||
this.basketButtons = document.querySelectorAll('.basket-btn');
|
||||
}
|
||||
|
||||
bindAddToBasket(handler) {
|
||||
this.basketButtons.forEach(button => {
|
||||
button.addEventListener('click', async (e) => {
|
||||
const card = e.target.closest('.card');
|
||||
const productId = card.dataset.id;
|
||||
const isInBasket = button.classList.contains('in-basket');
|
||||
|
||||
if (isInBasket) {
|
||||
await handler(productId, 'remove');
|
||||
button.classList.remove('in-basket');
|
||||
button.innerHTML = '<i class="bi bi-cart-plus me-1"></i>В корзину';
|
||||
} else {
|
||||
await handler(productId, 'add');
|
||||
button.classList.add('in-basket');
|
||||
button.innerHTML = '<i class="bi bi-cart-check me-1"></i>В корзине';
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
updateBasketButton(productId, isInBasket) {
|
||||
const buttons = document.querySelectorAll(`.basket-btn[data-id="${productId}"]`);
|
||||
buttons.forEach(button => {
|
||||
if (isInBasket) {
|
||||
button.classList.add('in-basket');
|
||||
button.innerHTML = '<i class="bi bi-cart-check me-1"></i>В корзине';
|
||||
} else {
|
||||
button.classList.remove('in-basket');
|
||||
button.innerHTML = '<i class="bi bi-cart-plus me-1"></i>В корзину';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
65
js/client.js
65
js/client.js
@@ -1,65 +0,0 @@
|
||||
const URL = "http://localhost:3000/";
|
||||
|
||||
const makeRequest = async (path, params, vars, method = "GET", data = null) => {
|
||||
try {
|
||||
const requestParams = params ? `?${params}` : "";
|
||||
const pathVariables = vars ? `/${vars}` : "";
|
||||
const options = { method };
|
||||
const hasBody = (method === "POST" || method === "PUT") && data;
|
||||
if (hasBody) {
|
||||
options.headers = { "Content-Type": "application/json;charset=utf-8" };
|
||||
options.body = JSON.stringify(data);
|
||||
}
|
||||
console.log(`${URL}${path}${pathVariables}${requestParams}`);
|
||||
const response = await fetch(`${URL}${path}${pathVariables}${requestParams}`, options);
|
||||
if (!response.ok) {
|
||||
throw new Error(`Response status: ${response?.status}`);
|
||||
}
|
||||
|
||||
const json = await response.json();
|
||||
console.debug(path, json);
|
||||
return json;
|
||||
} catch (error) {
|
||||
if (error instanceof SyntaxError) {
|
||||
throw new Error("There was a SyntaxError", error);
|
||||
} else {
|
||||
throw new Error("There was an error", error);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export async function getAllItems(path, query = "") {
|
||||
const url = `${URL}${path}?${query}`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
Accept: "application/json",
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error(`Failed to fetch ${url}:`, error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export const getItem = (path, id) => makeRequest(path, null, id);
|
||||
|
||||
export const createItem = async (path, data) => {
|
||||
const response = await fetch(`${URL}${path}`, {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||
// eslint-disable-next-line no-return-await
|
||||
return await response.json();
|
||||
};
|
||||
|
||||
export const updateItem = (path, id, data) => makeRequest(path, null, id, "PUT", data);
|
||||
|
||||
export const deleteItem = (path, id) => makeRequest(path, null, id, "DELETE");
|
||||
@@ -1,38 +0,0 @@
|
||||
import { LikesModel } from './model.js';
|
||||
import { LikesView } from './view.js';
|
||||
|
||||
export class LikesController {
|
||||
constructor() {
|
||||
this.model = new LikesModel();
|
||||
this.view = new LikesView();
|
||||
|
||||
this.init();
|
||||
}
|
||||
|
||||
init() {
|
||||
this.view.bindLikeButton(this.handleLikeAction.bind(this));
|
||||
this.updateLikeButtons();
|
||||
}
|
||||
|
||||
async handleLikeAction(productId, action) {
|
||||
const product = await this.getProductById(productId);
|
||||
|
||||
if (action === 'add') {
|
||||
await this.model.addToLikes(product);
|
||||
} else {
|
||||
await this.model.removeFromLikes(productId);
|
||||
}
|
||||
}
|
||||
|
||||
async getProductById(id) {
|
||||
const response = await fetch(`http://localhost:3000/shmots/${id}`);
|
||||
return await response.json();
|
||||
}
|
||||
|
||||
async updateLikeButtons() {
|
||||
const likes = await this.model.getLikes();
|
||||
likes.forEach(like => {
|
||||
this.view.updateLikeButton(like.id, true);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { apiService } from '../ApiService.js';
|
||||
|
||||
export class LikesModel {
|
||||
async getLikes() {
|
||||
return await apiService.get('likes');
|
||||
}
|
||||
|
||||
async addToLikes(product) {
|
||||
return await apiService.post('likes', product);
|
||||
}
|
||||
|
||||
async removeFromLikes(id) {
|
||||
return await apiService.delete('likes', id);
|
||||
}
|
||||
|
||||
async isLiked(productId) {
|
||||
const likes = await this.getLikes();
|
||||
return likes.some(like => like.id === productId);
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
export class LikesView {
|
||||
constructor() {
|
||||
this.likeButtons = document.querySelectorAll('.like-btn');
|
||||
}
|
||||
|
||||
bindLikeButton(handler) {
|
||||
this.likeButtons.forEach(button => {
|
||||
button.addEventListener('click', async (e) => {
|
||||
const card = e.target.closest('.card');
|
||||
const productId = card.dataset.id;
|
||||
const isLiked = button.classList.contains('liked');
|
||||
|
||||
if (isLiked) {
|
||||
await handler(productId, 'remove');
|
||||
button.classList.remove('liked');
|
||||
button.innerHTML = '<i class="bi bi-heart"></i> В избранное';
|
||||
} else {
|
||||
await handler(productId, 'add');
|
||||
button.classList.add('liked');
|
||||
button.innerHTML = '<i class="bi bi-heart-fill"></i> В избранном';
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
updateLikeButton(productId, isLiked) {
|
||||
const buttons = document.querySelectorAll(`.like-btn[data-id="${productId}"]`);
|
||||
buttons.forEach(button => {
|
||||
if (isLiked) {
|
||||
button.classList.add('liked');
|
||||
button.innerHTML = '<i class="bi bi-heart-fill"></i> В избранном';
|
||||
} else {
|
||||
button.classList.remove('liked');
|
||||
button.innerHTML = '<i class="bi bi-heart"></i> В избранное';
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
8
node_modules/.vite/deps/_metadata.json
generated
vendored
8
node_modules/.vite/deps/_metadata.json
generated
vendored
@@ -1,8 +1,8 @@
|
||||
{
|
||||
"hash": "761ccfbc",
|
||||
"configHash": "efa0c127",
|
||||
"lockfileHash": "9124da8c",
|
||||
"browserHash": "1c8e9837",
|
||||
"hash": "6ddd1b63",
|
||||
"configHash": "25cf0a03",
|
||||
"lockfileHash": "29e56d0d",
|
||||
"browserHash": "aef01c56",
|
||||
"optimized": {},
|
||||
"chunks": {}
|
||||
}
|
||||
Reference in New Issue
Block a user