diff --git a/ui/src/components/ChannelBadge.tsx b/ui/src/components/ChannelBadge.tsx new file mode 100644 index 0000000..15ecf0f --- /dev/null +++ b/ui/src/components/ChannelBadge.tsx @@ -0,0 +1,33 @@ +import { UserTablo } from "@ui/types/tablos.types"; +import { twMerge } from "tailwind-merge"; + +export const ChannelBadge = ({ + tablo, + displayTitle, + isOnline, +}: { + tablo: UserTablo | null; + displayTitle: string | undefined; + isOnline: boolean; +}) => { + const initials = + tablo?.name?.charAt(0)?.toUpperCase() || + displayTitle?.charAt(0)?.toUpperCase() || + "C"; + + return ( +
+
+ {initials} +
+ {isOnline && ( +
+ )} +
+ ); +}; diff --git a/ui/src/components/ChannelPreview.tsx b/ui/src/components/ChannelPreview.tsx index d8513f3..502642b 100644 --- a/ui/src/components/ChannelPreview.tsx +++ b/ui/src/components/ChannelPreview.tsx @@ -3,6 +3,7 @@ import { Badge } from "@ui/ui-library/badge"; import { ReactNode } from "react"; import { Channel } from "stream-chat"; import { twMerge } from "tailwind-merge"; +import { ChannelBadge } from "@ui/components/ChannelBadge"; interface ChannelPreviewProps { channel: Channel; @@ -80,8 +81,6 @@ export function ChannelPreview({ setActiveChannel?.(channel); }; - console.log({ displayTitle, tablo }); - return (
- {/* Avatar with online status */} -
-
-
- {tablo?.name?.charAt(0)?.toUpperCase() || - displayTitle?.charAt(0)?.toUpperCase() || - "C"} -
- {isOnline && ( -
- )} -
-
+ {/* Channel info */}
diff --git a/ui/src/components/CustomChannelHeader.tsx b/ui/src/components/CustomChannelHeader.tsx new file mode 100644 index 0000000..34754e6 --- /dev/null +++ b/ui/src/components/CustomChannelHeader.tsx @@ -0,0 +1,56 @@ +import { ChannelHeader, useChannelStateContext } from "stream-chat-react"; +import { ChannelBadge } from "./ChannelBadge"; +import { UserTablo } from "@ui/types/tablos.types"; + +interface CustomChannelHeaderProps { + tablos: UserTablo[]; + onToggleChannelList?: () => void; + isChannelListExpanded?: boolean; +} + +export const CustomChannelHeader = ({ + tablos, + onToggleChannelList, + isChannelListExpanded = false, +}: CustomChannelHeaderProps) => { + const { channel } = useChannelStateContext(); + + return ( +
+ {onToggleChannelList && ( + + )} + { + return ( + t.id === channel?.id) ?? null} + displayTitle={channel?.data?.config?.name} + isOnline={false} + /> + ); + }} + /> +
+ ); +}; diff --git a/ui/src/components/devis/CreateDevisModal.tsx b/ui/src/components/devis/CreateDevisModal.tsx index 0aa138f..85dc0de 100644 --- a/ui/src/components/devis/CreateDevisModal.tsx +++ b/ui/src/components/devis/CreateDevisModal.tsx @@ -88,7 +88,6 @@ export const CreateDevisModal = ({ {(validationState) => { - console.log(validationState); return validationState.validationErrors ? "Veuillez entrer une adresse email valide" : ""; diff --git a/ui/src/hooks/channel.ts b/ui/src/hooks/channel.ts index f62d8a4..6cd13b9 100644 --- a/ui/src/hooks/channel.ts +++ b/ui/src/hooks/channel.ts @@ -1,17 +1,18 @@ import { useEffect, useState } from "react"; import { Channel, StreamChat } from "stream-chat"; +import { useParams } from "react-router-dom"; -export const useChannel = ( - client: StreamChat, - channelId: string | undefined -) => { +export const useChannelFromUrl = (client: StreamChat) => { const [channel, setChannel] = useState(null); + const { channelId } = useParams(); useEffect(() => { if (channelId) { const channel = client.channel("messaging", channelId); channel.watch(); setChannel(channel); + } else { + setChannel(null); } }, [channelId, client]); - return channel; + return { channel, isChannelInUrl: !!channelId }; }; diff --git a/ui/src/pages/chat.tsx b/ui/src/pages/chat.tsx index b838f58..30a81c6 100644 --- a/ui/src/pages/chat.tsx +++ b/ui/src/pages/chat.tsx @@ -1,112 +1,52 @@ import { ChannelList, - ChannelHeader, MessageList, MessageInput, Window, Channel, + useChatContext, } from "stream-chat-react"; import { useUser } from "@ui/providers/UserStoreProvider"; import { ChannelPreview } from "@ui/components/ChannelPreview"; -import { useParams } from "react-router-dom"; import { StreamChat } from "stream-chat"; -import { useChannel } from "@ui/hooks/channel"; +import { useChannelFromUrl } from "@ui/hooks/channel"; import { useTablosList } from "@ui/hooks/tablos"; +import { CustomChannelHeader } from "@ui/components/CustomChannelHeader"; +import { useEffect, useState } from "react"; export function ChatPage({ client }: { client: StreamChat }) { const user = useUser(); const filters = { members: { $in: [user.id] }, type: "messaging" }; - const { channelId } = useParams(); - const channel = useChannel(client, channelId); + const { channel: channelFromUrl, isChannelInUrl } = useChannelFromUrl(client); + + const { channel, setActiveChannel } = useChatContext(); const { data: tablos } = useTablosList(); + const [isChannelListExpanded, setIsChannelListExpanded] = useState(false); - if (channel) { - return ( - - -
-
-
-
-
- {channel?.data?.config?.name?.charAt(0)?.toUpperCase() || - "C"} -
-
-

- {channel?.data?.config?.name || "Channel"} -

-

- {Object.keys(channel?.state?.members || {}).length}{" "} - members -

-
-
-
-
- - - -
-
-
- - -
-
- ); - } + const toggleChannelList = () => { + setIsChannelListExpanded(!isChannelListExpanded); + }; + + useEffect(() => { + if (channelFromUrl) { + setActiveChannel(channelFromUrl); + } else { + setIsChannelListExpanded(true); + } + }, [channelFromUrl]); return (
-
+
- + - + diff --git a/ui/src/pages/tablo.tsx b/ui/src/pages/tablo.tsx index 6c8e988..a3bfd89 100644 --- a/ui/src/pages/tablo.tsx +++ b/ui/src/pages/tablo.tsx @@ -291,13 +291,9 @@ export const TabloPage = () => { className="relative" onContextMenu={(e) => { e.preventDefault(); - // Only show context menu if user is admin - if (isAdmin) { - setContextMenuTablo( - contextMenuTablo === tablo.id ? null : tablo.id - ); - setContextMenuPosition({ x: e.clientX, y: e.clientY }); - } + // Show context menu for all users + setContextMenuTablo(contextMenuTablo === tablo.id ? null : tablo.id); + setContextMenuPosition({ x: e.clientX, y: e.clientY }); }} >
{
- {/* Contextual Menu - Only show for admins */} - {isAdmin && contextMenuTablo === tablo.id && contextMenuPosition && ( + {/* Contextual Menu */} + {contextMenuTablo === tablo.id && contextMenuPosition && (
{ Ouvrir le tablo */} - {/* Status change options */} -
-
- Changer le statut -
- - - + {/* Status change options - Only for admins */} + {isAdmin && ( + <> +
+
+ Changer le statut +
+ + + + + )}
)}
diff --git a/xtablo-expo/app/(home)/(tabs)/profile.tsx b/xtablo-expo/app/(home)/(tabs)/profile.tsx index 51e4ee3..9b65d56 100644 --- a/xtablo-expo/app/(home)/(tabs)/profile.tsx +++ b/xtablo-expo/app/(home)/(tabs)/profile.tsx @@ -12,8 +12,6 @@ export default function ProfileScreen() { const [displayName, setDisplayName] = useState(user?.full_name || ""); const [isEditing, setIsEditing] = useState(false); - console.log({ user }); - return ( diff --git a/xtablo-expo/hooks/user.ts b/xtablo-expo/hooks/user.ts index 799aea5..7feecbc 100644 --- a/xtablo-expo/hooks/user.ts +++ b/xtablo-expo/hooks/user.ts @@ -9,7 +9,6 @@ export const useGetUser = (): { user: User | null; isPending: boolean } => { queryKey: ["user"], queryFn: async () => { const { data } = await supabase.from("profiles").select("*"); - console.log(data); return data; }, });