page.tsx 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. // src/app/dashboard/page.tsx
  2. 'use client'
  3. import { Plus, Twitter, InstagramIcon, Facebook, Linkedin } from 'lucide-react';
  4. import { useState, useEffect } from 'react';
  5. import AddProfile from '@/components/profiles/addProfile';
  6. import { useTheme } from '@/contexts/themecontext';
  7. import { getProfilesByWorkspace, type Profile } from '@/lib/api/core';
  8. export default function DashboardPage() {
  9. const [showOnboarding, setShowOnboarding] = useState(false);
  10. const [profiles, setProfiles] = useState<Profile[]>([]);
  11. const [isLoading, setIsLoading] = useState(true);
  12. const { theme } = useTheme();
  13. useEffect(() => {
  14. const fetchProfiles = async () => {
  15. try {
  16. const workspaceId = localStorage.getItem('selectedWorkspaceId');
  17. if (!workspaceId) return;
  18. const fetchedProfiles = await getProfilesByWorkspace(workspaceId);
  19. setProfiles(fetchedProfiles);
  20. } catch (error) {
  21. console.error('Failed to fetch profiles:', error);
  22. } finally {
  23. setIsLoading(false);
  24. }
  25. };
  26. fetchProfiles();
  27. }, []);
  28. const handleNewProfileClick = () => {
  29. setShowOnboarding(true);
  30. };
  31. const handleOnboardingComplete = () => {
  32. setShowOnboarding(false);
  33. // Refresh profiles after creating a new one
  34. const workspaceId = localStorage.getItem('selectedWorkspaceId');
  35. if (workspaceId) {
  36. getProfilesByWorkspace(workspaceId).then(setProfiles);
  37. }
  38. };
  39. if (isLoading) {
  40. return (
  41. <div className="flex justify-center items-center h-full">
  42. <div className="w-8 h-8 border-4 border-blue-500 border-t-transparent rounded-full animate-spin" />
  43. </div>
  44. );
  45. }
  46. return (
  47. <div className="p-4">
  48. {showOnboarding && <AddProfile onComplete={handleOnboardingComplete} />}
  49. <div className="flex items-center justify-between mb-6">
  50. <h1 className={`text-2xl font-bold ${theme === 'dark' ? 'text-white' : 'text-gray-900'}`}>
  51. Tous les profils
  52. </h1>
  53. </div>
  54. {profiles.length === 0 ? (
  55. <div className={`text-center py-12 ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>
  56. <p className="text-lg mb-4">Aucun profil</p>
  57. <button
  58. onClick={handleNewProfileClick}
  59. className={`inline-flex items-center px-4 py-2 rounded-md ${
  60. theme === 'dark' ? 'bg-gray-800 hover:bg-gray-700' : 'bg-gray-100 hover:bg-gray-200'
  61. } transition-colors`}
  62. >
  63. <Plus className="w-5 h-5 mr-2" />
  64. Créer un profil
  65. </button>
  66. </div>
  67. ) : (
  68. <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 xl:grid-cols-4 gap-4">
  69. {profiles.map((profile) => (
  70. <ProfileCard
  71. key={profile.id}
  72. profile={profile}
  73. theme={theme}
  74. />
  75. ))}
  76. <NewProfileCard onClick={handleNewProfileClick} theme={theme} />
  77. </div>
  78. )}
  79. </div>
  80. );
  81. }
  82. function ProfileCard({ profile, theme }: { profile: Profile, theme: 'dark' | 'light' }) {
  83. const socialIcons = {
  84. twitter: <Twitter className="w-4 h-4 text-blue-400" />,
  85. instagram: <InstagramIcon className="w-4 h-4 text-pink-500" />,
  86. facebook: <Facebook className="w-4 h-4 text-blue-600" />,
  87. linkedin: <Linkedin className="w-4 h-4 text-blue-700" />
  88. };
  89. const getProfileIcon = () => {
  90. if (profile.socials && profile.socials.length > 0) {
  91. const firstSocial = profile.socials[0];
  92. return socialIcons[firstSocial.type as keyof typeof socialIcons] || '👤';
  93. }
  94. return '👤';
  95. };
  96. return (
  97. <div className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg p-4 hover:ring-2 hover:ring-blue-500/50 transition-all cursor-pointer shadow-lg`}>
  98. <div className="flex items-center space-x-4">
  99. <div className={`w-12 h-12 ${theme === 'dark' ? 'bg-gray-700' : 'bg-gray-100'} rounded-full flex items-center justify-center text-2xl`}>
  100. {getProfileIcon()}
  101. </div>
  102. <div>
  103. <h3 className={`font-medium ${theme === 'dark' ? 'text-white' : 'text-gray-900'}`}>
  104. {profile.name}
  105. </h3>
  106. <p className={`text-sm ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'}`}>
  107. @{profile.name.toLowerCase()}
  108. </p>
  109. </div>
  110. </div>
  111. <div className="mt-4">
  112. <div className="flex flex-wrap gap-2">
  113. {profile.socials?.map((social) => (
  114. <div
  115. key={social.id}
  116. className={`flex items-center px-2 py-1 rounded ${
  117. theme === 'dark' ? 'bg-gray-700' : 'bg-gray-100'
  118. }`}
  119. >
  120. {socialIcons[social.type as keyof typeof socialIcons]}
  121. <span className="ml-1 text-sm">{social.identifier}</span>
  122. </div>
  123. ))}
  124. </div>
  125. </div>
  126. </div>
  127. );
  128. }
  129. function NewProfileCard({ onClick, theme }: { onClick: () => void, theme: 'dark' | 'light' }) {
  130. return (
  131. <div
  132. className={`${theme === 'dark' ? 'bg-gray-800' : 'bg-white'} rounded-lg aspect-video p-4 flex flex-col justify-center items-center hover:ring-2 hover:ring-blue-500/50 transition-all cursor-pointer shadow-lg`}
  133. onClick={onClick}
  134. >
  135. <div className={`w-12 h-12 ${theme === 'dark' ? 'bg-gray-700' : 'bg-gray-100'} rounded-full flex items-center justify-center`}>
  136. <Plus className={`w-6 h-6 ${theme === 'dark' ? 'text-gray-500' : 'text-gray-400'}`} />
  137. </div>
  138. <p className={`text-sm ${theme === 'dark' ? 'text-gray-400' : 'text-gray-600'} mt-2`}>Ajouter un nouveau profil</p>
  139. </div>
  140. );
  141. }