Używamy cookies, żeby zwiększyć Twoje doświadczenia na stronie
CodeWorlds

Professional Feed i Networking - Aktualizacje zawodowe

LinkedIn feed różni się od Twittera - tutaj dzielisz się aktualizacjami zawodowymi, sukcesami i insightami branżowymi.

Feed Post Types

1type PostType = 'text' | 'article' | 'image' | 'video' | 'job_change' | 'work_anniversary';
2
3interface FeedPost {
4  id: string;
5  type: PostType;
6  author: {
7    id: string;
8    name: string;
9    avatar: string;
10    headline: string;
11  };
12  content: string;
13  media?: {
14    type: 'image' | 'video' | 'document';
15    url: string;
16    thumbnail?: string;
17  };
18  likes: number;
19  comments: number;
20  reposts: number;
21  timestamp: Date;
22
23  // Special fields for job change posts
24  jobChange?: {
25    previousCompany: string;
26    newCompany: string;
27    newPosition: string;
28  };
29}

Feed Post Card

1'use client';
2
3import { useState } from 'react';
4
5function FeedPostCard({ post }: { post: FeedPost }) {
6  const [liked, setLiked] = useState(false);
7  const [showComments, setShowComments] = useState(false);
8
9  return (
10    <div className="bg-white rounded-lg shadow mb-3">
11      {/* Header */}
12      <div className="flex items-start gap-3 p-6 pb-3">
13        <img
14          src={post.author.avatar}
15          alt={post.author.name}
16          className="w-12 h-12 rounded-full"
17        />
18        <div className="flex-1">
19          <div className="flex items-start justify-between">
20            <div>
21              <h3 className="font-bold hover:underline cursor-pointer">
22                {post.author.name}
23              </h3>
24              <p className="text-sm text-gray-600">{post.author.headline}</p>
25              <p className="text-xs text-gray-500 mt-1">
26                {formatTimeAgo(post.timestamp)} • 🌍
27              </p>
28            </div>
29            <button className="text-gray-500 hover:bg-gray-100 rounded-full p-2">
30              •••
31            </button>
32          </div>
33        </div>
34      </div>
35
36      {/* Content */}
37      <div className="px-6 pb-3">
38        {/* Job Change Celebration */}
39        {post.type === 'job_change' && post.jobChange && (
40          <div className="mb-3 bg-gradient-to-r from-blue-50 to-green-50 border border-blue-200 rounded-lg p-4">
41            <p className="font-semibold mb-2">🎉 Started a new position</p>
42            <p className="text-sm text-gray-700">
43              {post.jobChange.newPosition} at {post.jobChange.newCompany}
44            </p>
45          </div>
46        )}
47
48        {/* Text Content */}
49        <p className="text-gray-900 whitespace-pre-wrap mb-3">{post.content}</p>
50
51        {/* Media */}
52        {post.media && post.media.type === 'image' && (
53          <img
54            src={post.media.url}
55            alt="Post media"
56            className="w-full rounded-lg"
57          />
58        )}
59      </div>
60
61      {/* Stats */}
62      <div className="px-6 py-2 border-t border-b flex items-center justify-between text-sm text-gray-600">
63        <button className="hover:underline">
64          {post.likes} likes
65        </button>
66        <div className="flex gap-3">
67          <button className="hover:underline">
68            {post.comments} comments
69          </button>
70          <button className="hover:underline">
71            {post.reposts} reposts
72          </button>
73        </div>
74      </div>
75
76      {/* Actions */}
77      <div className="px-6 py-2 flex items-center justify-around">
78        <button
79          onClick={() => setLiked(!liked)}
80          className={`flex items-center gap-2 px-4 py-2 rounded hover:bg-gray-100 transition ${
81            liked ? 'text-blue-600 font-semibold' : 'text-gray-600'
82          }`}
83        >
84          <span className="text-xl">{liked ? '👍' : '👍🏻'}</span>
85          Like
86        </button>
87        <button
88          onClick={() => setShowComments(!showComments)}
89          className="flex items-center gap-2 px-4 py-2 rounded hover:bg-gray-100 text-gray-600"
90        >
91          <span className="text-xl">💬</span>
92          Comment
93        </button>
94        <button className="flex items-center gap-2 px-4 py-2 rounded hover:bg-gray-100 text-gray-600">
95          <span className="text-xl">🔄</span>
96          Repost
97        </button>
98        <button className="flex items-center gap-2 px-4 py-2 rounded hover:bg-gray-100 text-gray-600">
99          <span className="text-xl">📤</span>
100          Send
101        </button>
102      </div>
103
104      {/* Comment Input */}
105      {showComments && (
106        <div className="px-6 pb-4 border-t pt-4">
107          <div className="flex gap-3">
108            <img
109              src="/current-user-avatar.jpg"
110              alt="You"
111              className="w-10 h-10 rounded-full"
112            />
113            <input
114              type="text"
115              className="flex-1 px-4 py-2 border rounded-full hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-blue-500"
116            />
117          </div>
118        </div>
119      )}
120    </div>
121  );
122}

Create Post Modal

1'use client';
2
3import { useState } from 'react';
4
5export default function CreatePostModal({ onClose, onSubmit }: {
6  onClose: () => void;
7  onSubmit: (content: string) => void;
8}) {
9  const [content, setContent] = useState('');
10
11  return (
12    <div className="fixed inset-0 bg-black bg-opacity-50 z-50 flex items-center justify-center p-4">
13      <div className="bg-white rounded-lg max-w-2xl w-full">
14        <div className="flex items-center justify-between p-4 border-b">
15          <h2 className="text-xl font-bold">Create a post</h2>
16          <button
17            onClick={onClose}
18            className="text-gray-500 hover:text-gray-700 text-2xl"
19          >
2021          </button>
22        </div>
23
24        <div className="p-4">
25          <div className="flex gap-3 mb-4">
26            <img
27              src="/current-user-avatar.jpg"
28              alt="You"
29              className="w-12 h-12 rounded-full"
30            />
31            <div>
32              <h3 className="font-bold">Your Name</h3>
33              <button className="text-sm text-gray-600 hover:underline">
34                Post to anyone 🌍
35              </button>
36            </div>
37          </div>
38
39          <textarea
40            value={content}
41            onChange={(e) => setContent(e.target.value)}
42            className="w-full p-3 text-lg resize-none outline-none"
43            rows={8}
44            autoFocus
45          />
46
47          <div className="flex items-center gap-2 text-gray-500 mt-4">
48            <button className="p-2 hover:bg-gray-100 rounded text-xl">📷</button>
49            <button className="p-2 hover:bg-gray-100 rounded text-xl">🎬</button>
50            <button className="p-2 hover:bg-gray-100 rounded text-xl">📄</button>
51            <button className="p-2 hover:bg-gray-100 rounded text-xl">📊</button>
52          </div>
53        </div>
54
55        <div className="p-4 border-t flex justify-end">
56          <button
57            onClick={() => {
58              onSubmit(content);
59              onClose();
60            }}
61            disabled={!content.trim()}
62            className="px-6 py-2 bg-blue-600 text-white rounded-full font-bold hover:bg-blue-700 disabled:bg-gray-300 disabled:cursor-not-allowed"
63          >
64            Post
65          </button>
66        </div>
67      </div>
68    </div>
69  );
70}

Connections Page - Sieć kontaktów

1interface Connection {
2  id: string;
3  name: string;
4  avatar: string;
5  headline: string;
6  mutualConnections: number;
7  connectedDate: Date;
8}
9
10function ConnectionCard({ connection }: { connection: Connection }) {
11  return (
12    <div className="bg-white border rounded-lg p-4 hover:shadow-lg transition">
13      <div className="flex items-start gap-3">
14        <img
15          src={connection.avatar}
16          alt={connection.name}
17          className="w-16 h-16 rounded-full"
18        />
19        <div className="flex-1">
20          <h3 className="font-bold hover:underline cursor-pointer mb-1">
21            {connection.name}
22          </h3>
23          <p className="text-sm text-gray-600 mb-2 line-clamp-2">
24            {connection.headline}
25          </p>
26          <p className="text-xs text-gray-500">
27            {connection.mutualConnections} mutual connections
28          </p>
29        </div>
30      </div>
31
32      <div className="flex gap-2 mt-4">
33        <button className="flex-1 py-2 border-2 border-blue-600 text-blue-600 rounded-full font-semibold hover:bg-blue-50">
34          Message
35        </button>
36        <button className="px-4 py-2 border border-gray-300 rounded-full hover:bg-gray-50">
37          •••
38        </button>
39      </div>
40    </div>
41  );
42}
43
44export default function ConnectionsPage({ connections }: { connections: Connection[] }) {
45  return (
46    <div className="max-w-6xl mx-auto p-4">
47      <div className="bg-white rounded-lg shadow p-6 mb-4">
48        <h1 className="text-2xl font-bold mb-4">
49          {connections.length} Connections
50        </h1>
51        <input
52          type="text"
53          className="w-full px-4 py-2 border rounded-lg"
54        />
55      </div>
56
57      <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
58        {connections.map(conn => (
59          <ConnectionCard key={conn.id} connection={conn} />
60        ))}
61      </div>
62    </div>
63  );
64}

Podsumowanie 🎓

Feed post types - text, job change, article, media ✅ Feed post card - likes, comments, reposts ✅ Create post - modal with media options ✅ Job change celebration - special badge ✅ Engagement actions - like, comment, repost, send ✅ Professional tone - business-focused content ✅ Connections page - network management ✅ Connection cards - mutual connections, message button

Masz teraz kompletny LinkedIn clone z profiles, jobs i networking! 💼

Do zobaczenia! 🚀

Przejdź do CodeWorlds