habits.andr33v.ru/app/pages/index.vue

205 lines
4.8 KiB
Vue

<template>
<div class="home-page">
<div v-if="isAuthenticated && user" class="dashboard-content">
<h1>Welcome, {{ user.nickname }}!</h1>
<p>This is your dashboard. Let's get those habits done!</p>
<div class="habits-section">
<h2>My Habits</h2>
<div v-if="habitsPending">Loading habits...</div>
<div v-else-if="habitsError">Could not load habits.</div>
<div v-else-if="habits && habits.length > 0">
<div v-for="habit in habits" :key="habit.id" class="habit-card">
<h3>{{ habit.name }}</h3>
<div class="history-grid">
<div v-for="day in last14Days" :key="day.toISOString()" class="day-cell" :class="{ 'completed': isCompleted(habit, day) }">
<span class="day-label">{{ day.getDate() }}</span>
</div>
</div>
<button @click="completeHabit(habit.id)" :disabled="isCompleted(habit, today)">
{{ isCompleted(habit, today) ? 'Completed Today' : 'Complete for Today' }}
</button>
</div>
</div>
<div v-else>
<p>You have no habits yet. Go to the <NuxtLink to="/habits">My Habits</NuxtLink> page to create one.</p>
</div>
</div>
<div class="links">
<NuxtLink to="/habits" class="button">Manage Habits</NuxtLink>
<NuxtLink to="/village" class="button">My Village</NuxtLink>
<NuxtLink to="/leaderboard" class="button">Leaderboard</NuxtLink>
</div>
</div>
<div v-else class="welcome-content">
<h1>Добро пожаловать в SmurfHabits!</h1>
<p>Отслеживайте свои привычки и развивайте свою деревню.</p>
<div class="auth-buttons">
<NuxtLink to="/login" class="button primary">Войти</NuxtLink>
<NuxtLink to="/register" class="button secondary">Зарегистрироваться</NuxtLink>
</div>
</div>
</div>
</template>
<script setup>
import { computed } from 'vue';
const { user, isAuthenticated } = useAuth();
const api = useApi();
// --- Habits Data ---
const { data: habits, pending: habitsPending, error: habitsError, refresh: refreshHabits } = await useFetch('/api/habits', {
lazy: true,
server: false,
});
// --- Date Logic ---
const today = new Date();
const last14Days = computed(() => {
const dates = [];
for (let i = 13; i >= 0; i--) {
const date = new Date();
date.setDate(date.getDate() - i);
dates.push(date);
}
return dates;
});
const isSameDay = (d1, d2) => {
d1 = new Date(d1);
d2 = new Date(d2);
return d1.getFullYear() === d2.getFullYear() &&
d1.getMonth() === d2.getMonth() &&
d1.getDate() === d2.getDate();
};
const isCompleted = (habit, date) => {
return habit.completions.some(c => isSameDay(c.date, date));
};
// --- Actions ---
const completeHabit = async (habitId) => {
try {
await api(`/api/habits/${habitId}/complete`, { method: 'POST' });
await refreshHabits(); // Refresh the habits data to show the new completion
} catch (err) {
alert(err.data?.message || 'Failed to complete habit.');
}
};
</script>
<style scoped>
.home-page {
padding: 40px;
text-align: center;
}
.habits-section {
margin-top: 40px;
margin-bottom: 40px;
}
.habit-card {
background: #fff;
border-radius: 8px;
padding: 20px;
margin: 20px auto;
max-width: 800px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.history-grid {
display: grid;
grid-template-columns: repeat(14, 1fr);
gap: 5px;
margin: 20px 0;
}
.day-cell {
width: 40px;
height: 40px;
border: 1px solid #e2e8f0;
border-radius: 4px;
display: flex;
justify-content: center;
align-items: center;
background-color: #f8fafc;
}
.day-cell.completed {
background-color: #4ade80;
color: white;
}
.day-label {
font-size: 0.8em;
}
.welcome-content {
margin-top: 50px;
}
.welcome-content h1 {
font-size: 2.5em;
margin-bottom: 20px;
color: #333;
}
.welcome-content p {
font-size: 1.2em;
color: #555;
margin-bottom: 40px;
}
.auth-buttons {
display: flex;
justify-content: center;
gap: 20px;
}
.button {
display: inline-block;
padding: 12px 25px;
border-radius: 8px;
text-decoration: none;
font-weight: bold;
font-size: 1.1em;
transition: background-color 0.3s ease;
border: 1px solid transparent;
}
.button.primary {
background-color: #007bff;
color: white;
}
.button.primary:hover {
background-color: #0056b3;
}
.button.secondary {
background-color: #6c757d;
color: white;
}
.button.secondary:hover {
background-color: #5a6268;
}
.links {
display: flex;
justify-content: center;
gap: 20px;
margin: 40px 0;
}
.links a.button {
background-color: #e9ecef;
color: #333;
}
.links a.button:hover {
background-color: #dee2e6;
}
</style>