astro_avtourist/frontend/src/components/reviews/ReviewFormContainer.tsx

147 lines
No EOL
5.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { createSignal, onMount, Show } from "solid-js";
import ReviewForm from "./ReviewForm";
interface ToastMessage {
type: "success" | "error";
message: string;
}
interface User {
id: string;
name: string;
email: string;
avatar?: string;
}
export default function ReviewFormContainer() {
const [isAuthenticated, setIsAuthenticated] = createSignal(false);
const [currentUser, setCurrentUser] = createSignal<User | undefined>(undefined);
const [isLoading, setIsLoading] = createSignal(true);
const [toast, setToast] = createSignal<ToastMessage | null>(null);
const showToast = (message: ToastMessage): void => {
setToast(message);
setTimeout(() => setToast(null), 3000);
};
onMount(async () => {
try {
const response = await fetch("/api/auth/me", {
method: "GET",
credentials: "include",
});
const data = await response.json();
if (data.authenticated && data.user) {
setIsAuthenticated(true);
setCurrentUser({
id: data.user.id,
name: data.user.name || "Пользователь",
email: data.user.email,
avatar: data.user.avatar,
});
}
} catch (error) {
console.error("[ReviewForm] Ошибка проверки авторизации:", error);
} finally {
setIsLoading(false);
}
});
const handleSubmit = async (data: {
name: string;
surname: string;
profession: string;
rating: number;
text: string;
}) => {
try {
const response = await fetch("/api/reviews", {
method: "POST",
headers: { "Content-Type": "application/json" },
credentials: "include",
body: JSON.stringify({
name: data.name,
surname: data.surname,
profession: data.profession,
rating: data.rating,
text: data.text,
}),
});
if (!response.ok) {
const errorData = await response.json();
throw new Error(errorData.error || "Failed to create review");
}
showToast({ type: "success", message: "Спасибо! Ваш отзыв отправлен на модерацию." });
} catch (error) {
console.error("[ReviewForm] Ошибка создания отзыва:", error);
showToast({ type: "error", message: "Не удалось отправить отзыв. Попробуйте позже." });
}
};
return (
<>
<Show when={toast()}>
{(t) => (
<div
class={`fixed bottom-4 right-4 px-6 py-3 rounded-xl shadow-lg transition-all duration-300 z-50 ${
t().type === "success"
? "bg-green-500 text-white"
: "bg-red-500 text-white"
}`}
>
{t().message}
</div>
)}
</Show>
<Show when={isLoading()}>
</Show>
<Show when={!isLoading()}>
<Show when={isAuthenticated()} fallback={
<div class="mx-auto" style="max-width: 700px;">
<div class="bg-linear-to-br from-gray-50 to-gray-100 rounded-2xl p-8 md:p-12 border border-gray-200 text-center" style="background: linear-gradient(135deg, #f8fafc 0%, #f1f5f9 100%);">
<div class="w-20 h-20 mx-auto mb-6 rounded-full flex items-center justify-center" style="background: linear-gradient(135deg, rgba(37, 99, 235, 0.2) 0%, rgba(30, 64, 175, 0.3) 100%);">
<svg class="w-10 h-10 text-blue-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/>
</svg>
</div>
<h4 class="text-xl font-semibold text-gray-900 mb-3">
Авторизуйтесь, чтобы оставить отзыв
</h4>
<p class="text-gray-600 mb-6">
Чтобы поделиться своим опытом, пожалуйста, войдите в аккаунт.
</p>
<a
href={`/auth/sign-in?redirect=${encodeURIComponent(window.location.pathname)}`}
class="inline-flex items-center justify-center font-semibold transition-all duration-300 rounded-md cursor-pointer px-6 py-3 text-lg"
style="background: linear-gradient(to bottom, #2563eb, #1e40af); color: white; box-shadow: 0 2px 4px rgba(37, 99, 235, 0.3);"
>
<svg class="w-5 h-5 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 16l-4-4m0 0l4-4m-4 4h14m-5 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h7a3 3 0 013 3v1"/>
</svg>
Войдите в аккаунт
</a>
<p class="mt-4 text-sm text-gray-600">
Нет аккаунта?{" "}
<a
href={`/auth/sign-up?redirect=${encodeURIComponent(window.location.pathname)}`}
class="font-medium hover:underline"
style="color: #2563eb;"
>
Зарегистрироваться
</a>
</p>
</div>
</div>
}>
<ReviewForm onSubmit={handleSubmit} user={currentUser()} />
</Show>
</Show>
</>
);
}