import {ref, computed, onMounted} from 'vue'
-import { useRouter} from 'vue-router'
-import { Ripple, Notify } from 'quasar'
+import {useRouter} from 'vue-router'
+import {Ripple, Notify} from 'quasar'
import axios from "axios";
-import { parseStringPromise } from 'xml2js'
+import {parseStringPromise} from 'xml2js'
import CONFIG from "@/core/config.js";
-defineExpose({ directives: { ripple: Ripple } })
+defineExpose({directives: {ripple: Ripple}})
const router = useRouter()
@@ -168,19 +168,19 @@ const teamName = ref('Digital Dream Team')
// --- Участники ---
const members = ref([
- { id: 1, name: 'Иван Иванов', role: 'Team Lead', avatar: 'https://randomuser.me/api/portraits/men/32.jpg' },
- { id: 2, name: 'Мария Петрова', role: 'Frontend', avatar: 'https://randomuser.me/api/portraits/women/44.jpg' },
- { id: 3, name: 'Алексей Смирнов', role: 'Backend', avatar: 'https://randomuser.me/api/portraits/men/65.jpg' },
- { id: 4, name: 'Анна Кузнецова', role: 'Designer', avatar: 'https://randomuser.me/api/portraits/women/56.jpg' },
- { id: 5, name: 'Дмитрий Орлов', role: 'QA', avatar: 'https://randomuser.me/api/portraits/men/78.jpg' },
+ {id: 1, name: 'Иван Иванов', role: 'Team Lead', avatar: 'https://randomuser.me/api/portraits/men/32.jpg'},
+ {id: 2, name: 'Мария Петрова', role: 'Frontend', avatar: 'https://randomuser.me/api/portraits/women/44.jpg'},
+ {id: 3, name: 'Алексей Смирнов', role: 'Backend', avatar: 'https://randomuser.me/api/portraits/men/65.jpg'},
+ {id: 4, name: 'Анна Кузнецова', role: 'Designer', avatar: 'https://randomuser.me/api/portraits/women/56.jpg'},
+ {id: 5, name: 'Дмитрий Орлов', role: 'QA', avatar: 'https://randomuser.me/api/portraits/men/78.jpg'},
])
// --- Конкурсы ---
const contests = ref([
- { id: 1, title: 'Hackathon 2024', description: 'Ежегодный хакатон для стартапов' },
- { id: 2, title: 'CodeFest', description: 'Соревнование по программированию' },
- { id: 3, title: 'UI/UX Challenge', description: 'Конкурс дизайна интерфейсов' },
- { id: 4, title: 'AI Innovation', description: 'Инициатива в области искусственного интеллекта' },
+ {id: 1, title: 'Hackathon 2024', description: 'Ежегодный хакатон для стартапов'},
+ {id: 2, title: 'CodeFest', description: 'Соревнование по программированию'},
+ {id: 3, title: 'UI/UX Challenge', description: 'Конкурс дизайна интерфейсов'},
+ {id: 4, title: 'AI Innovation', description: 'Инициатива в области искусственного интеллекта'},
])
// --- Активность ---
@@ -198,8 +198,15 @@ const weekDays = ['пн', 'ср', 'пт'];
const activityGrid = computed(() => {
const weeks = [];
let week = [];
- let firstDay = new Date(activityData.value[0]?.date || new Date());
- firstDay.setDate(firstDay.getDate() - 364); // Начинаем с 365 дней назад
+ const firstDay = new Date();
+ firstDay.setDate(firstDay.getDate() - 364); // Год назад от текущей даты
+ const dayOfWeek = firstDay.getDay();
+ const offset = dayOfWeek === 0 ? 6 : dayOfWeek - 1; // Смещение для выравнивания по понедельнику
+
+ // Добавляем пустые ячейки в начало
+ for (let i = 0; i < offset; i++) {
+ week.push({ date: '', count: 0 });
+ }
for (let i = 0; i < 365; i++) {
const date = new Date(firstDay);
@@ -218,11 +225,11 @@ const activityGrid = computed(() => {
// Цвета активности (как в Gitea)
function getActivityColor(count) {
- if (count === 0) return '#ebedf0';
- if (count <= 2) return '#c6e48b';
- if (count <= 4) return '#7bc96f';
- if (count <= 6) return '#239a3b';
- return '#196127';
+ if (count === 0) return '#ede9fe'; // Светлый фон карточек
+ if (count <= 2) return '#d8cff9'; // Светлый сиреневый
+ if (count <= 4) return '#a287ff'; // Светлый фиолетовый
+ if (count <= 6) return '#7c3aed'; // Яркий фиолетовый
+ return '#4f046f'; // Темно-фиолетовый
}
// Позиционирование подписей месяцев
@@ -239,24 +246,23 @@ const username = 'andrei';
async function loadActivity() {
try {
const response = await axios.get(`${CONFIG.BASE_URL}/rss/${username}/`);
- activityData.value = response.data;
-
- // Дополняем до 365 дней
+ const fetchedData = response.data.map(item => ({
+ date: item.date,
+ count: parseInt(item.count, 10) || 0
+ }));
+ const dataMap = new Map(fetchedData.map(d => [d.date, d.count]));
const lastDate = new Date();
const startDate = new Date(lastDate);
startDate.setDate(lastDate.getDate() - 364);
- const existingDates = new Set(activityData.value.map(d => d.date));
activityData.value = [];
for (let i = 0; i < 365; i++) {
const date = new Date(startDate);
date.setDate(startDate.getDate() + i);
const dateStr = date.toISOString().slice(0, 10);
- const dayData = response.data.find(d => d.date === dateStr) || { date: dateStr, count: 0 };
- activityData.value.push(dayData);
+ const count = dataMap.get(dateStr) || 0;
+ activityData.value.push({date: dateStr, count});
}
-
- // Сортировка не требуется, так как мы формируем массив в правильном порядке
} catch (error) {
console.error('Ошибка загрузки активности:', error);
Notify.create({
@@ -274,7 +280,7 @@ async function loadActivity() {
const date = new Date(startDate);
date.setDate(startDate.getDate() + i);
const dateStr = date.toISOString().slice(0, 10);
- activityData.value.push({ date: dateStr, count: 0 });
+ activityData.value.push({date: dateStr, count: 0});
}
}
}
@@ -294,6 +300,18 @@ function decreaseScale() {
\ No newline at end of file