🚀 Initial commit: Versão atual do TrackSteel APP

This commit is contained in:
2026-03-18 21:17:53 +00:00
commit bde410c9ad
633 changed files with 108150 additions and 0 deletions
+476
View File
@@ -0,0 +1,476 @@
import { useState } from 'react';
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { supabase } from '@/integrations/supabase/client';
import { Database } from '@/integrations/supabase/types';
import { toast } from 'sonner';
type Task = Database['public']['Tables']['tasks']['Row'];
type TaskInsert = Database['public']['Tables']['tasks']['Insert'];
type TaskUpdate = Database['public']['Tables']['tasks']['Update'];
export const useTasks = () => {
const queryClient = useQueryClient();
// Fetch active tasks (not completed)
const {
data: activeTasks = [],
isLoading: isLoadingActive,
refetch: refetchActiveTasks,
error: activeTasksError
} = useQuery({
queryKey: ['tasks', 'active'],
queryFn: async () => {
console.log('🔍 Fetching active tasks...');
// Check if user is authenticated
const { data: { user }, error: authError } = await supabase.auth.getUser();
if (authError) {
console.error('❌ Auth error when fetching active tasks:', authError);
throw new Error('Erro de autenticação: ' + authError.message);
}
if (!user) {
console.error('❌ No authenticated user found');
throw new Error('Usuário não autenticado');
}
console.log('✅ User authenticated:', user.email);
const { data, error } = await supabase
.from('tasks')
.select('*')
.eq('is_completed', false)
.order('due_date', { ascending: true, nullsFirst: false });
if (error) {
console.error('❌ Error fetching active tasks:', error);
console.error('Error details:', {
code: error.code,
message: error.message,
details: error.details,
hint: error.hint
});
throw new Error('Erro ao buscar tarefas ativas: ' + error.message);
}
console.log('✅ Active tasks fetched successfully:', data?.length || 0, 'tasks');
console.log('📋 Tasks data:', data);
return data || [];
},
});
// Fetch recent completed tasks (last 24 hours)
const {
data: recentCompletedTasks = [],
isLoading: isLoadingRecentCompleted,
refetch: refetchRecentCompleted,
error: recentCompletedError
} = useQuery({
queryKey: ['tasks', 'recent-completed'],
queryFn: async () => {
console.log('🔍 Fetching recent completed tasks...');
// Check if user is authenticated
const { data: { user }, error: authError } = await supabase.auth.getUser();
if (authError || !user) {
console.error('❌ Auth error when fetching recent completed tasks:', authError);
throw new Error('Usuário não autenticado');
}
const oneDayAgo = new Date();
oneDayAgo.setDate(oneDayAgo.getDate() - 1);
const { data, error } = await supabase
.from('tasks')
.select('*')
.eq('is_completed', true)
.gte('completed_at', oneDayAgo.toISOString())
.order('completed_at', { ascending: false });
if (error) {
console.error('❌ Error fetching recent completed tasks:', error);
throw new Error('Erro ao buscar tarefas concluídas: ' + error.message);
}
console.log('✅ Recent completed tasks fetched:', data?.length || 0);
return data || [];
},
});
// Fetch completed tasks by current user (last 30 days for history)
const {
data: completedTasks = [],
isLoading: isLoadingCompleted,
refetch: refetchCompletedTasks,
error: completedTasksError
} = useQuery({
queryKey: ['tasks', 'completed'],
queryFn: async () => {
console.log('🔍 Fetching completed tasks by current user...');
// Check if user is authenticated
const { data: { user }, error: authError } = await supabase.auth.getUser();
if (authError || !user) {
console.error('❌ Auth error when fetching completed tasks:', authError);
throw new Error('Usuário não autenticado');
}
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
const { data, error } = await supabase
.from('tasks')
.select('*')
.eq('is_completed', true)
.eq('completed_by', user.id)
.gte('completed_at', thirtyDaysAgo.toISOString())
.order('completed_at', { ascending: false });
if (error) {
console.error('❌ Error fetching completed tasks:', error);
throw new Error('Erro ao buscar histórico de tarefas: ' + error.message);
}
console.log('✅ Completed tasks by user fetched:', data?.length || 0);
return data || [];
},
});
// Fetch tasks assigned by current user and completed by others (last 30 days for history)
const {
data: assignedCompletedTasks = [],
isLoading: isLoadingAssignedCompleted,
refetch: refetchAssignedCompletedTasks,
error: assignedCompletedTasksError
} = useQuery({
queryKey: ['tasks', 'assigned-completed'],
queryFn: async () => {
console.log('🔍 Fetching assigned completed tasks...');
// Check if user is authenticated
const { data: { user }, error: authError } = await supabase.auth.getUser();
if (authError || !user) {
console.error('❌ Auth error when fetching assigned completed tasks:', authError);
throw new Error('Usuário não autenticado');
}
const thirtyDaysAgo = new Date();
thirtyDaysAgo.setDate(thirtyDaysAgo.getDate() - 30);
const { data, error } = await supabase
.from('tasks')
.select('*')
.eq('is_completed', true)
.eq('created_by', user.id)
.neq('completed_by', user.id)
.gte('completed_at', thirtyDaysAgo.toISOString())
.order('completed_at', { ascending: false });
if (error) {
console.error('❌ Error fetching assigned completed tasks:', error);
throw new Error('Erro ao buscar tarefas atribuídas concluídas: ' + error.message);
}
console.log('✅ Assigned completed tasks fetched:', data?.length || 0);
return data || [];
},
});
// Fetch available OFs from ficha_tecnica_contratos table
const { data: availableOFs = [] } = useQuery({
queryKey: ['ofs'],
queryFn: async () => {
console.log('🔍 Fetching available OFs...');
const { data, error } = await supabase
.from('ficha_tecnica_contratos')
.select('of_number, cliente')
.order('of_number');
if (error) {
console.error('❌ Error fetching OFs:', error);
throw error;
}
console.log('✅ Available OFs fetched:', data?.length || 0);
return data || [];
},
});
// Fetch available users - use direct query with type assertion for RPC
const { data: availableUsers = [] } = useQuery({
queryKey: ['users'],
queryFn: async () => {
console.log('🔍 Fetching available users...');
// Check if user is authenticated
const { data: { user }, error: authError } = await supabase.auth.getUser();
if (authError || !user) {
console.error('❌ Auth error when fetching users:', authError);
throw new Error('Usuário não autenticado');
}
console.log('✅ User authenticated for fetching users:', user.email);
try {
// Use RPC function to bypass RLS restrictions for user listing
const { data, error } = await supabase.rpc('get_all_users_for_tasks' as any);
if (error) {
console.error('❌ Error fetching users via RPC:', error);
// Fallback to direct query if RPC fails
const { data: fallbackData, error: fallbackError } = await supabase
.from('profiles')
.select('id, email, full_name')
.eq('status', 'active')
.order('email');
if (fallbackError) {
console.error('❌ Error fetching users (fallback):', fallbackError);
throw new Error('Erro ao buscar usuários: ' + fallbackError.message);
}
console.log('✅ Available users fetched (fallback):', fallbackData?.length || 0);
return fallbackData || [];
}
// Type assertion for RPC result
const typedData = data as Array<{ id: string; email: string; full_name: string }>;
console.log('✅ Available users fetched via RPC:', typedData?.length || 0);
return typedData || [];
} catch (rpcError) {
console.error('❌ RPC call failed, using fallback:', rpcError);
// Fallback to direct query
const { data: fallbackData, error: fallbackError } = await supabase
.from('profiles')
.select('id, email, full_name')
.eq('status', 'active')
.order('email');
if (fallbackError) {
console.error('❌ Error fetching users (fallback):', fallbackError);
throw new Error('Erro ao buscar usuários: ' + fallbackError.message);
}
console.log('✅ Available users fetched (fallback):', fallbackData?.length || 0);
return fallbackData || [];
}
},
});
// Create task mutation
const { mutate: createTask, isPending: isCreating } = useMutation({
mutationFn: async (taskData: Omit<TaskInsert, 'task_ref' | 'id' | 'created_at' | 'updated_at' | 'created_by'>) => {
console.log('🚀 Creating task with data:', taskData);
// Check if user is authenticated
const { data: { user }, error: authError } = await supabase.auth.getUser();
if (authError) {
console.error('❌ Auth error when creating task:', authError);
throw new Error('Erro de autenticação: ' + authError.message);
}
if (!user) {
console.error('❌ No authenticated user found when creating task');
throw new Error('Usuário não autenticado');
}
console.log('✅ User authenticated for task creation:', user.email);
// Generate a unique task_ref using timestamp and random string
const timestamp = Date.now();
const randomString = Math.random().toString(36).substring(2, 8);
const uniqueTaskRef = `TASK-${timestamp}-${randomString}`;
// Prepare the complete task data
const completeTaskData: TaskInsert = {
...taskData,
created_by: user.id,
task_ref: uniqueTaskRef, // Use unique task_ref instead of placeholder
};
console.log('📝 Complete task data for insertion:', completeTaskData);
const { data, error } = await supabase
.from('tasks')
.insert(completeTaskData)
.select()
.single();
if (error) {
console.error('❌ Error creating task:', error);
console.error('Error details:', {
code: error.code,
message: error.message,
details: error.details,
hint: error.hint
});
throw new Error('Erro ao criar tarefa: ' + error.message);
}
console.log('✅ Task created successfully:', data);
return data;
},
onSuccess: (data) => {
console.log('🎉 Task creation successful, invalidating queries...');
queryClient.invalidateQueries({ queryKey: ['tasks'] });
toast.success('Tarefa criada com sucesso!');
},
onError: (error) => {
console.error('💥 Task creation failed:', error);
const errorMessage = error instanceof Error ? error.message : 'Erro desconhecido ao criar tarefa';
toast.error(errorMessage);
},
});
// Update task mutation
const { mutate: updateTask, isPending: isUpdating } = useMutation({
mutationFn: async ({ id, updates }: { id: string; updates: TaskUpdate }) => {
console.log('📝 Updating task:', id, updates);
const { data, error } = await supabase
.from('tasks')
.update(updates)
.eq('id', id)
.select()
.single();
if (error) {
console.error('❌ Error updating task:', error);
throw new Error('Erro ao atualizar tarefa: ' + error.message);
}
console.log('✅ Task updated successfully:', data);
return data;
},
onSuccess: () => {
console.log('🎉 Task update successful, invalidating queries...');
queryClient.invalidateQueries({ queryKey: ['tasks'] });
toast.success('Tarefa atualizada com sucesso!');
},
onError: (error) => {
console.error('💥 Task update failed:', error);
const errorMessage = error instanceof Error ? error.message : 'Erro ao atualizar tarefa';
toast.error(errorMessage);
},
});
// Complete task mutation
const { mutate: completeTask, isPending: isCompleting } = useMutation({
mutationFn: async (id: string) => {
console.log('✅ Completing task:', id);
const { data: { user } } = await supabase.auth.getUser();
if (!user) throw new Error('User not authenticated');
const { data, error } = await supabase
.from('tasks')
.update({
is_completed: true,
completed_at: new Date().toISOString(),
completed_by: user.id,
status: 'concluido'
})
.eq('id', id)
.select()
.single();
if (error) {
console.error('❌ Error completing task:', error);
throw new Error('Erro ao concluir tarefa: ' + error.message);
}
console.log('✅ Task completed successfully:', data);
return data;
},
onSuccess: () => {
console.log('🎉 Task completion successful, invalidating queries...');
queryClient.invalidateQueries({ queryKey: ['tasks'] });
toast.success('Tarefa concluída com sucesso!');
},
onError: (error) => {
console.error('💥 Task completion failed:', error);
const errorMessage = error instanceof Error ? error.message : 'Erro ao concluir tarefa';
toast.error(errorMessage);
},
});
// Delete task mutation
const { mutate: deleteTask, isPending: isDeleting } = useMutation({
mutationFn: async (id: string) => {
console.log('🗑️ Deleting task:', id);
const { error } = await supabase
.from('tasks')
.delete()
.eq('id', id);
if (error) {
console.error('❌ Error deleting task:', error);
throw new Error('Erro ao deletar tarefa: ' + error.message);
}
console.log('✅ Task deleted successfully');
},
onSuccess: () => {
console.log('🎉 Task deletion successful, invalidating queries...');
queryClient.invalidateQueries({ queryKey: ['tasks'] });
toast.success('Tarefa deletada com sucesso!');
},
onError: (error) => {
console.error('💥 Task deletion failed:', error);
const errorMessage = error instanceof Error ? error.message : 'Erro ao deletar tarefa';
toast.error(errorMessage);
},
});
// Refetch all tasks function
const refetchTasks = () => {
console.log('🔄 Refetching all tasks...');
refetchActiveTasks();
refetchRecentCompleted();
refetchCompletedTasks();
refetchAssignedCompletedTasks();
};
const isLoading = isLoadingActive || isLoadingRecentCompleted || isLoadingCompleted || isLoadingAssignedCompleted;
// Log any query errors
if (activeTasksError) {
console.error('❌ Active tasks query error:', activeTasksError);
}
if (recentCompletedError) {
console.error('❌ Recent completed tasks query error:', recentCompletedError);
}
if (completedTasksError) {
console.error('❌ Completed tasks query error:', completedTasksError);
}
if (assignedCompletedTasksError) {
console.error('❌ Assigned completed tasks query error:', assignedCompletedTasksError);
}
return {
activeTasks,
recentCompletedTasks,
completedTasks,
assignedCompletedTasks,
availableOFs,
availableUsers,
isLoading,
createTask,
updateTask,
deleteTask,
completeTask,
isCreating,
isUpdating,
isDeleting,
isCompleting,
refetchTasks,
// Expose errors for debugging
errors: {
activeTasksError,
recentCompletedError,
completedTasksError,
assignedCompletedTasksError
}
};
};