File size: 4,172 Bytes
075a2b6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// src/components/TileCard.tsx
import React from 'react';

// Define the TypeScript interfaces corresponding to Pydantic schemas
interface VerificationMark {
    verification_type: string;
    is_expert_verified: boolean;
    expert_orcid_id?: string;
    expert_name?: string;
    verification_date?: string;
    verification_count: number;
}

interface KnowledgeTile {
    tile_id: string;
    domain_id: string;
    topic: string;
    content_preview: string;
    created_at: string;
    updated_at: string;
    verification_mark: VerificationMark;
    contributor_id?: string;
    confidence_score: number;
    tags: string[];
}

interface DomainConfig {
    domain_id: string;
    name: string;
}

interface TileCardProps {
    tile: KnowledgeTile;
    availableDomains?: DomainConfig[];
    onDomainChange?: (tileId: string, newDomainId: string) => void;
}

const TileCard: React.FC<TileCardProps> = ({ tile, availableDomains, onDomainChange }) => {
    const getVerificationColor = (type: string) => {
        switch (type) {
            case 'expert':
            case 'multi_expert':
                return 'border-green-500';
            case 'community':
                return 'border-blue-500';
            default:
                return 'border-gray-500';
        }
    };

    return (
        <div className={`panel-section ${getVerificationColor(tile.verification_mark.verification_type)} border-l-4`}>
            <div className="flex justify-between items-start">
                <h4 className="font-bold text-lg mb-1">{tile.topic}</h4>
                {availableDomains && availableDomains.length > 0 && onDomainChange ? (
                    <select
                        value={tile.domain_id}
                        onChange={(e) => onDomainChange(tile.tile_id, e.target.value)}
                        style={{
                            fontSize: '12px',
                            padding: '4px 8px',
                            backgroundColor: '#2a2a2a',
                            border: '1px solid #444',
                            borderRadius: '4px',
                            color: '#aaa',
                            cursor: 'pointer'
                        }}
                    >
                        {availableDomains.map(domain => (
                            <option key={domain.domain_id} value={domain.domain_id}>
                                {domain.name}
                            </option>
                        ))}
                    </select>
                ) : (
                    <span className="text-xs text-gray-400 font-mono">{tile.domain_id}</span>
                )}
            </div>
            <p className="text-sm text-gray-300 mb-3">{tile.content_preview}</p>
            
            <div className="text-xs text-gray-500 space-y-1">
                <div>
                    <strong>Confidence:</strong> 
                    <span style={{ color: `hsl(${(tile.confidence_score * 120)}, 100%, 50%)` }}>
                        {` ${(tile.confidence_score * 100).toFixed(1)}%`}
                    </span>
                </div>
                <div>
                    <strong>Verification:</strong> {tile.verification_mark.verification_type} ({tile.verification_mark.verification_count})
                </div>
                {tile.verification_mark.is_expert_verified && (
                    <div>
                        <strong>Expert:</strong> {tile.verification_mark.expert_name || tile.verification_mark.expert_orcid_id}
                    </div>
                )}
                <div>
                    <strong>Updated:</strong> {new Date(tile.updated_at).toLocaleDateString()}
                </div>
            </div>
            
            {tile.tags.length > 0 && (
                <div className="mt-2 flex flex-wrap gap-1">
                    {tile.tags.map(tag => (
                        <span key={tag} className="text-xs bg-gray-700 text-gray-300 px-2 py-1 rounded-full">
                            {tag}
                        </span>
                    ))}
                </div>
            )}
        </div>
    );
};

export default TileCard;