11class NimbusTeam extends HTMLElement {
22 static #selectors = {
33 UserCardTmpl : "nimbus-team-user-card-tmpl" ,
4+ UserCardAvatar : ".user-card-avatar" ,
5+ UserCardEmail : ".user-card-email a" ,
6+ UserCardSocial : {
7+ bluesky : ".icon-social-bsky" ,
8+ linkedin : ".icon-social-linkedin" ,
9+ mastodon : ".icon-social-mastodon" ,
10+ } ,
11+ UserCardPhone : ".user-card-phone a" ,
12+ UserCardRole : ".user-card-role" ,
13+ UserCardTitle : ".user-card-title" ,
414 } ;
515
616 #shadow;
717
18+ #users;
19+
820 constructor ( ) {
921 super ( ) ;
1022 this . #shadow = this . attachShadow ( { mode : "open" } ) ;
1123 this . #loadCSS( ) ;
1224 }
1325
1426 connectedCallback ( ) {
15- const listContainer = document . createElement ( "ul" ) ;
27+ this . #render( ) ;
28+ }
29+
30+ async #render( ) {
1631 const template = document . getElementById (
1732 NimbusTeam . #selectors. UserCardTmpl
1833 ) ;
1934
20- if ( template ) {
21- const content = template . content . cloneNode ( true ) ;
22-
23- listContainer . classList . add ( "card-list" ) ;
24- listContainer . appendChild ( content ) ;
35+ if ( ! template ) {
36+ return ;
37+ }
2538
26- this . #shadow. appendChild ( listContainer ) ;
39+ if ( ! this . #users) {
40+ await this . #loadUsers( ) ;
2741 }
42+
43+ const listContainer = document . createElement ( "ul" ) ;
44+ listContainer . classList . add ( "card-list" ) ;
45+
46+ this . #users. forEach ( ( user ) => {
47+ const userCard = template . content . cloneNode ( true ) ;
48+ const email = userCard . querySelector ( NimbusTeam . #selectors. UserCardEmail ) ;
49+ const phone = userCard . querySelector ( NimbusTeam . #selectors. UserCardPhone ) ;
50+
51+ const bluesky = userCard . querySelector (
52+ NimbusTeam . #selectors. UserCardSocial . bluesky
53+ ) ;
54+ const linkedin = userCard . querySelector (
55+ NimbusTeam . #selectors. UserCardSocial . linkedin
56+ ) ;
57+ const mastodon = userCard . querySelector (
58+ NimbusTeam . #selectors. UserCardSocial . mastodon
59+ ) ;
60+
61+ // Because all social icons have the same accessible text content
62+ // we can use any of them to get the unprocessed text content.
63+ const accText = bluesky . querySelector ( "span" ) . textContent ;
64+
65+ userCard . querySelector (
66+ NimbusTeam . #selectors. UserCardTitle
67+ ) . textContent = `${ user . firstName } ${ user . lastName } ` ;
68+
69+ userCard . querySelector ( NimbusTeam . #selectors. UserCardAvatar ) . src =
70+ user . avatarURL ;
71+
72+ userCard . querySelector ( NimbusTeam . #selectors. UserCardRole ) . textContent =
73+ user . role ;
74+
75+ email . textContent = user . email ;
76+ email . href = `mailto:${ user . email } ` ;
77+
78+ phone . textContent = user . telephone ;
79+ phone . href = `tel:${ user . telephone } ` ;
80+
81+ bluesky . href = user . bluesky ;
82+ bluesky . querySelector ( "span" ) . textContent = accText
83+ . replace ( "@employee" , user . firstName )
84+ . replace ( "@platform" , "Bluesky" ) ;
85+
86+ linkedin . href = user . linkedin ;
87+ linkedin . querySelector ( "span" ) . textContent = accText
88+ . replace ( "@employee" , user . firstName )
89+ . replace ( "@platform" , "LinkedIn" ) ;
90+
91+ mastodon . href = user . mastodon ;
92+ mastodon . querySelector ( "span" ) . textContent = accText
93+ . replace ( "@employee" , user . firstName )
94+ . replace ( "@platform" , "Mastodon" ) ;
95+
96+ listContainer . appendChild ( userCard ) ;
97+ } ) ;
98+
99+ this . #shadow. appendChild ( listContainer ) ;
28100 }
29101
30102 /**
@@ -46,6 +118,16 @@ class NimbusTeam extends HTMLElement {
46118 this . #shadow. appendChild ( style ) ;
47119 }
48120 }
121+
122+ async #loadUsers( ) {
123+ const response = await fetch (
124+ "https://fictionalfolks.netlify.app/.netlify/functions/users?count=1"
125+ ) ;
126+
127+ if ( response . ok ) {
128+ this . #users = await response . json ( ) ;
129+ }
130+ }
49131}
50132
51133customElements . define ( "nimbus-team" , NimbusTeam ) ;
0 commit comments