diff --git a/app/pages/admin/groups/[id].vue b/app/pages/admin/groups/[id].vue
index 1be038e..43a9cfe 100644
--- a/app/pages/admin/groups/[id].vue
+++ b/app/pages/admin/groups/[id].vue
@@ -159,7 +159,7 @@ const fetchGroup = async () => {
headers: { Authorization: `Bearer ${auth.token.value}` }
})
group.value = data.group
- members.value = data.members || []
+ members.value = data.group.members || []
} catch (e) {
console.error('Failed to fetch group', e)
navigateTo('/admin/groups')
diff --git a/app/pages/canvases.vue b/app/pages/canvases.vue
index aa88b49..881ecca 100644
--- a/app/pages/canvases.vue
+++ b/app/pages/canvases.vue
@@ -9,13 +9,13 @@
Мои Карты
-
@@ -223,11 +223,19 @@ const showCreateModal = ref(false)
const importInput = ref(null)
const activeTab = ref('personal')
- const newCanvas = reactive({
- name: '',
- visibility: 'private',
- groupId: ''
- })
+const newCanvas = reactive({
+ name: '',
+ visibility: 'private',
+ groupId: ''
+})
+
+const openCreateModal = () => {
+ newCanvas.name = ''
+ newCanvas.visibility = 'private'
+ newCanvas.groupId = ''
+ showSettingsModal.value = false
+ showCreateModal.value = true
+}
const showSettingsModal = ref(false)
const saving = ref(false)
@@ -293,9 +301,9 @@ const filteredCanvases = computed(() => {
switch (activeTab.value) {
case 'personal':
- return canvases.value.filter(c => c.ownerId === userId && !c.groupId)
+ return canvases.value.filter(c => c.ownerId === userId && (!c.groupId || c.groupId === ''))
case 'team':
- return canvases.value.filter(c => !!c.groupId)
+ return canvases.value.filter(c => c.groupId && c.groupId !== '')
case 'public':
return canvases.value.filter(c => c.isPublic)
default:
diff --git a/app/pages/tasks.vue b/app/pages/tasks.vue
index 887736d..0c83a9a 100644
--- a/app/pages/tasks.vue
+++ b/app/pages/tasks.vue
@@ -163,21 +163,18 @@ const columns = [
// Fetch all tasks for current user
const fetchTasks = async () => {
try {
- const res = await fetch('/api/tasks', {
+ const data = await $fetch('/api/tasks', {
headers: { Authorization: `Bearer ${auth.token.value}` }
})
- if (res.ok) {
- const data = await res.json()
- tasks.value = data.tasks || []
-
- // Split tasks into columns
- columns.forEach(col => {
- columnsData[col.id] = tasks.value.filter(t => {
- const taskState = t.state || t.data?.state || 'todo'
- return taskState === col.id
- })
+ tasks.value = data.tasks || []
+
+ // Split tasks into columns
+ columns.forEach(col => {
+ columnsData[col.id] = tasks.value.filter(t => {
+ const taskState = t.state || t.data?.state || 'todo'
+ return taskState === col.id
})
- }
+ })
} catch (e) {
console.error('Failed to load tasks', e)
} finally {
@@ -187,8 +184,10 @@ const fetchTasks = async () => {
const fetchCanvases = async () => {
try {
- const res = await $fetch('/api/canvas')
- availableCanvases.value = res.canvases || []
+ const data = await $fetch('/api/canvas', {
+ headers: { Authorization: `Bearer ${auth.token.value}` }
+ })
+ availableCanvases.value = data.canvases || []
if (availableCanvases.value.length > 0) {
newTask.canvasId = availableCanvases.value[0].id
}
diff --git a/app/server/api/auth/google.post.ts b/app/server/api/auth/google.post.ts
index e490661..35b6e01 100644
--- a/app/server/api/auth/google.post.ts
+++ b/app/server/api/auth/google.post.ts
@@ -34,7 +34,8 @@ export default defineEventHandler(async (event) => {
const fbUser: FirebaseUser = verifyRes.users[0]
const email = fbUser.email
- const username = email.split('@')[0]
+ // Очищаем username: заменяем пробелы на дефисы и убираем спецсимволы
+ const username = email.split('@')[0].toLowerCase().replace(/\s+/g, '-').replace(/[^a-z0-9-_]/g, '')
const userId = fbUser.localId
const user = await prisma.user.upsert({
diff --git a/app/server/api/groups/[id]/add-member.post.ts b/app/server/api/groups/[id]/add-member.post.ts
index 386b51f..8c32855 100644
--- a/app/server/api/groups/[id]/add-member.post.ts
+++ b/app/server/api/groups/[id]/add-member.post.ts
@@ -5,28 +5,28 @@ export default defineEventHandler(async (event) => {
const adminUser = requireAuth(event)
const groupId = getRouterParam(event, 'id')
const body = await readBody(event)
- const { email, role = 'member' } = body
+ const { email, userId, role = 'member' } = body
- if (!groupId || !email) {
- throw createError({ statusCode: 400, message: 'Group ID and Email are required' })
+ if (!groupId || (!email && !userId)) {
+ throw createError({ statusCode: 400, message: 'Group ID and either Email or User ID are required' })
}
- // 1. Проверяем, является ли текущий пользователь админом группы или глобальным админом
- const group = await prisma.group.findUnique({
- where: { id: groupId }
- })
-
+ // 1. Проверяем права
+ const group = await prisma.group.findUnique({ where: { id: groupId } })
if (!group || (group.ownerId !== adminUser.id && adminUser.role !== 'admin')) {
throw createError({ statusCode: 403, message: 'Only group owners or admins can add members' })
}
- // 2. Ищем пользователя по email
- const userToAdd = await prisma.user.findUnique({
- where: { email }
- })
+ // 2. Находим пользователя
+ let userToAdd = null
+ if (userId) {
+ userToAdd = await prisma.user.findUnique({ where: { id: userId } })
+ } else if (email) {
+ userToAdd = await prisma.user.findUnique({ where: { email } })
+ }
if (!userToAdd) {
- throw createError({ statusCode: 404, message: 'User with this email not found in system' })
+ throw createError({ statusCode: 404, message: 'User not found' })
}
// 3. Добавляем в группу