Sifa professional network frontend (Next.js, React, TailwindCSS) sifa.id/
at main 84 lines 2.9 kB view raw
1'use client'; 2 3import { useTranslations } from 'next-intl'; 4import { EditableSection, EditableEntry, CERTIFICATION_FIELDS } from '@/components/profile-editor'; 5import { 6 certificationToValues, 7 valuesToCertification, 8} from '@/components/profile-editor/section-converters'; 9import { formatTimelineDate } from './timeline'; 10import { sortByDateDesc, certDateExtractor } from '@/lib/sort-by-date'; 11import type { ProfileCertification } from '@/lib/types'; 12 13interface CredentialsSectionProps { 14 certifications: ProfileCertification[]; 15 isOwnProfile?: boolean; 16} 17 18export function CredentialsSection({ certifications, isOwnProfile }: CredentialsSectionProps) { 19 const t = useTranslations('sections'); 20 21 if (!certifications.length && !isOwnProfile) return null; 22 23 return ( 24 <section className="mt-8" aria-label={t('credentials')}> 25 <h2 className="mb-4 text-xl font-semibold"> 26 {t('credentials')} 27 {certifications.length > 0 && ( 28 <span className="ml-2 text-sm font-normal text-muted-foreground"> 29 {certifications.length} 30 </span> 31 )} 32 </h2> 33 <EditableSection<ProfileCertification> 34 maxVisible={5} 35 sectionTitle={t('credentials')} 36 profileKey="certifications" 37 isOwnProfile={isOwnProfile} 38 fields={CERTIFICATION_FIELDS} 39 toValues={certificationToValues} 40 fromValues={ 41 valuesToCertification as unknown as ( 42 v: Record<string, string | boolean>, 43 ) => Omit<ProfileCertification, 'rkey'> 44 } 45 collection="id.sifa.profile.certification" 46 sortItems={(items) => sortByDateDesc(items, certDateExtractor)} 47 renderEntry={(cert, controls) => ( 48 <EditableEntry 49 key={cert.rkey} 50 isOwnProfile={isOwnProfile} 51 onEdit={controls?.onEdit ?? (() => {})} 52 onDelete={controls?.onDelete ?? (() => {})} 53 entryLabel={cert.name} 54 > 55 <div className="flex items-start justify-between gap-2"> 56 <div className="min-w-0"> 57 <p className="font-medium"> 58 {cert.credentialUrl ? ( 59 <a 60 href={cert.credentialUrl} 61 className="underline-offset-4 hover:underline" 62 target="_blank" 63 rel="noopener noreferrer" 64 > 65 {cert.name} 66 </a> 67 ) : ( 68 cert.name 69 )} 70 </p> 71 <p className="text-sm text-muted-foreground">{cert.issuingOrg}</p> 72 </div> 73 {cert.issueDate && ( 74 <span className="shrink-0 text-xs text-muted-foreground"> 75 {formatTimelineDate(cert.issueDate)} 76 </span> 77 )} 78 </div> 79 </EditableEntry> 80 )} 81 /> 82 </section> 83 ); 84}