Create frontend

This commit is contained in:
IgorVolochay
2026-08-13 11:35:00 +03:00
parent 343c108e51
commit 9327ac53eb
33 changed files with 2083 additions and 87 deletions
+66
View File
@@ -0,0 +1,66 @@
/**
* API service — all backend requests for This OR That.
* All endpoints return { result, error } (BaseResponse).
*/
const BASE_URL = process.env.REACT_APP_API_URL || '';
async function request(method, path, body = null) {
const options = {
method,
headers: { 'Content-Type': 'application/json' },
};
if (body) {
options.body = JSON.stringify(body);
}
const response = await fetch(`${BASE_URL}${path}`, options);
const data = await response.json();
return data;
}
const GET = (path) => request('GET', path);
const POST = (path, body) => request('POST', path, body);
const PATCH = (path, body) => request('PATCH', path, body);
export const api = {
// Users
checkUser: (userId) =>
GET(`/check_user?user_id=${userId}`),
getUser: (userId) =>
GET(`/get_user?user_id=${userId}`),
addUser: ({ user_id, username, first_name, last_name, photo_url }) =>
POST('/add_user', { user_id, username, first_name, last_name, photo_url }),
// Cards
getCard: (cardId) =>
GET(`/get_card?card_id=${cardId}`),
getRandomCards: (userId) =>
GET(`/get_random_cards?user_id=${userId}`),
selectChoice: (userId, cardId, choice) =>
PATCH('/select_choice', { user_id: userId, card_id: cardId, choice }),
addCard: (choiceA, choiceB, authorId) =>
POST('/add_card', { choice_A: choiceA, choice_B: choiceB, author_id: authorId }),
// Reactions
likeCard: (userId, cardId) =>
PATCH('/like_card', { user_id: userId, card_id: cardId }),
dislikeCard: (userId, cardId) =>
PATCH('/dislike_card', { user_id: userId, card_id: cardId }),
// Comments
addComment: (authorId, cardId, commentText) =>
POST('/comment', { author_id: authorId, card_id: cardId, comment_text: commentText }),
// TODO: GET /get_comments — endpoint not yet implemented on backend
getComments: (cardId) => {
console.warn('GET /get_comments not implemented on backend yet');
return Promise.resolve({ result: [], error: false });
},
};
+55
View File
@@ -0,0 +1,55 @@
/**
* Auth service — detects Telegram WebApp user or falls back to mock.
* Auto-registers user on backend if not yet registered.
*/
const MOCK_USER = {
id: 999995,
first_name: 'Dev',
last_name: 'User',
username: 'devuser',
photo_url: '',
};
function getTelegramUser() {
try {
const tg = window.Telegram?.WebApp;
const user = tg?.initDataUnsafe?.user;
if (user && user.id) {
return {
id: user.id,
first_name: user.first_name || '',
last_name: user.last_name || '',
username: user.username || '',
photo_url: user.photo_url || '',
};
}
} catch {
// Telegram SDK not available
}
return null;
}
export const currentUser = getTelegramUser() ?? MOCK_USER;
export const isTelegram = !!getTelegramUser();
export function initTelegramApp() {
const tg = window.Telegram?.WebApp;
if (tg) {
tg.ready();
tg.expand();
}
}
export function showBackButton(onBack) {
const tg = window.Telegram?.WebApp;
if (tg?.BackButton) {
tg.BackButton.show();
tg.BackButton.onClick(onBack);
return () => {
tg.BackButton.offClick(onBack);
tg.BackButton.hide();
};
}
return () => { };
}