Hackathon: better frontend (#61)
* feat: enhance team browsing with member count and view team option * feat: add default banner image for teams without a custom banner * feat: implement user profile page and user layout component * feat: improve browse team filtering layout * feat: limit join request button visibility based on team member count * feat: enhance user profile and team dashboard layouts for improved responsiveness * feat: add location, bio, and skills fields to user profile schema and form * feat: enhance team display and user information layout for better readability * feat: update join request button visibility logic based on user team membership * feat: enhance team and user profile layouts with improved text truncation and responsiveness
This commit is contained in:
@@ -37,7 +37,10 @@ export const useTeams = (params?: {
|
||||
queryFn: async () => {
|
||||
try {
|
||||
// Supabase client now has auth context from setSession()
|
||||
let query = supabase.from('teams').select('*');
|
||||
let query = supabase.from('teams').select(`
|
||||
*,
|
||||
members:team_members(id)
|
||||
`);
|
||||
|
||||
// Filter by visibility
|
||||
if (params?.visibility) {
|
||||
@@ -691,3 +694,46 @@ export const useLeaveTeam = () => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// Get Teams by User ID
|
||||
export const useTeamsByUserId = (userId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['teams-by-user', userId],
|
||||
queryFn: async () => {
|
||||
if (!userId) {
|
||||
return { data: [] };
|
||||
}
|
||||
|
||||
// Query team_members to find teams where user is a member
|
||||
const { data: memberships, error: membershipsError } = await supabase
|
||||
.from('team_members')
|
||||
.select(`
|
||||
team_id,
|
||||
team:teams(
|
||||
id,
|
||||
name,
|
||||
logo,
|
||||
banner,
|
||||
description,
|
||||
city,
|
||||
visibility,
|
||||
leader_id,
|
||||
created_at
|
||||
)
|
||||
`)
|
||||
.eq('user_id', userId)
|
||||
.eq('status', 'active');
|
||||
|
||||
if (membershipsError) {
|
||||
console.error('Failed to fetch user teams:', membershipsError);
|
||||
return { data: [] };
|
||||
}
|
||||
|
||||
// Extract teams from memberships
|
||||
const teams = memberships?.map((m: any) => m.team).filter(Boolean) || [];
|
||||
|
||||
return { data: teams };
|
||||
},
|
||||
enabled: !!userId,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -92,3 +92,23 @@ export const useUpdateUserById = () => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useUserDetailsById = (userId: string) => {
|
||||
return useQuery({
|
||||
queryKey: ['user-supabase', userId],
|
||||
queryFn: async () => {
|
||||
const { data, error } = await supabase
|
||||
.from('users')
|
||||
.select('*')
|
||||
.eq('id', userId)
|
||||
.single();
|
||||
|
||||
if (error) {
|
||||
throw new Error(error.message || 'Failed to fetch user');
|
||||
}
|
||||
|
||||
return { data };
|
||||
},
|
||||
enabled: !!userId,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -76,6 +76,9 @@ export const userOnboardingSchema = z.object({
|
||||
export const userEditProfileSchema = z.object({
|
||||
fullname: z.string().min(3, 'Nama lengkap minimal 3 karakter'),
|
||||
avatar: z.string().url('Avatar harus berupa URL yang valid').nullable().optional(),
|
||||
location: z.string().optional(),
|
||||
bio: z.string().max(500, 'Bio maksimal 500 karakter').optional(),
|
||||
skills: z.array(z.string()).optional(),
|
||||
});
|
||||
|
||||
export type TTeamCreateForm = z.infer<typeof teamCreateSchema>;
|
||||
|
||||
Reference in New Issue
Block a user