your personal website on atproto - mirror blento.app

feat: add empty blento

+111 -18
+15 -12
src/lib/website/EditableWebsite.svelte
··· 31 31 import { compressImage } from '../helper'; 32 32 import Account from './Account.svelte'; 33 33 import EditBar from './EditBar.svelte'; 34 + import { user } from '$lib/atproto'; 34 35 35 36 let { 36 37 data ··· 744 745 </div> 745 746 </Sidebar> 746 747 747 - <EditBar 748 - {data} 749 - bind:linkValue 750 - bind:isSaving 751 - bind:showingMobileView 752 - bind:showSettings 753 - {newCard} 754 - {addLink} 755 - {save} 756 - {handleImageInputChange} 757 - {handleVideoInputChange} 758 - /> 748 + {#if user.isLoggedIn} 749 + <EditBar 750 + {data} 751 + bind:linkValue 752 + bind:isSaving 753 + bind:showingMobileView 754 + bind:showSettings 755 + {newCard} 756 + {addLink} 757 + {save} 758 + {handleImageInputChange} 759 + {handleVideoInputChange} 760 + /> 761 + {/if} 759 762 760 763 <Toaster /> 761 764 </Context>
+85
src/lib/website/EmptyState.svelte
··· 1 + <script lang="ts"> 2 + import { login, user } from '$lib/atproto'; 3 + import BaseCard from '$lib/cards/BaseCard/BaseCard.svelte'; 4 + import Card from '$lib/cards/Card/Card.svelte'; 5 + import type { Item, WebsiteData } from '$lib/types'; 6 + import type { ActorIdentifier } from '@atcute/lexicons'; 7 + import { Button } from '@foxui/core'; 8 + 9 + let { data }: { data: WebsiteData } = $props(); 10 + 11 + let cards = $derived.by((): Item[] => { 12 + const items: Item[] = []; 13 + 14 + // Name + "No blento yet" card 15 + items.push({ 16 + id: 'empty-main', 17 + x: 0, 18 + y: 0, 19 + w: 6, 20 + h: 2, 21 + mobileX: 0, 22 + mobileY: 0, 23 + mobileW: 8, 24 + mobileH: 3, 25 + cardType: 'text', 26 + color: 'red', 27 + cardData: { 28 + text: `## No blento yet!`, 29 + textAlign: 'center', 30 + verticalAlign: 'center' 31 + } 32 + }); 33 + 34 + // Bluesky social icon 35 + items.push({ 36 + id: 'empty-bluesky', 37 + x: 0, 38 + y: 2, 39 + w: 2, 40 + h: 2, 41 + mobileX: 0, 42 + mobileY: 3, 43 + mobileW: 3, 44 + mobileH: 3, 45 + cardType: 'bigsocial', 46 + cardData: { 47 + platform: 'bluesky', 48 + href: `https://bsky.app/profile/${data.handle}`, 49 + color: '0285FF' 50 + } 51 + }); 52 + 53 + return items; 54 + }); 55 + 56 + let maxHeight = $derived(cards.reduce((max, item) => Math.max(max, item.y + item.h), 0)); 57 + 58 + let maxMobileHeight = $derived( 59 + cards.reduce((max, item) => Math.max(max, item.mobileY + item.mobileH), 0) 60 + ); 61 + </script> 62 + 63 + {#each cards as item (item.id)} 64 + <BaseCard {item}> 65 + <Card {item} /> 66 + </BaseCard> 67 + {/each} 68 + 69 + <!-- Spacer for grid height --> 70 + <div class="hidden @[42rem]/grid:block" style="height: {(maxHeight / 8) * 100}cqw;"></div> 71 + <div class="@[42rem]/grid:hidden" style="height: {(maxMobileHeight / 4) * 100}cqw;"></div> 72 + 73 + {#if !user.isLoggedIn} 74 + <div 75 + class="dark:bg-base-950 border-base-200 dark:border-base-900 fixed top-4 right-4 z-20 flex flex-col gap-4 rounded-2xl border bg-white p-4 shadow-lg" 76 + > 77 + <span class="text-sm font-semibold">Login to edit your page</span> 78 + 79 + <Button 80 + onclick={async () => { 81 + await login(data.handle as ActorIdentifier); 82 + }}>Login</Button 83 + > 84 + </div> 85 + {/if}
+11 -6
src/lib/website/Website.svelte
··· 10 10 import Head from './Head.svelte'; 11 11 import type { Did, Handle } from '@atcute/lexicons'; 12 12 import QRModalProvider from '$lib/components/qr/QRModalProvider.svelte'; 13 + import EmptyState from './EmptyState.svelte'; 13 14 14 15 let { data }: { data: WebsiteData } = $props(); 15 16 ··· 55 56 > 56 57 <div></div> 57 58 <div bind:this={container} class="@container/grid relative col-span-3 px-2 py-8 lg:px-8"> 58 - {#each data.cards.toSorted(sortItems) as item (item.id)} 59 - <BaseCard {item}> 60 - <Card {item} /> 61 - </BaseCard> 62 - {/each} 63 - <div style="height: {(maxHeight / 8) * 100}cqw;"></div> 59 + {#if data.cards.length === 0} 60 + <EmptyState {data} /> 61 + {:else} 62 + {#each data.cards.toSorted(sortItems) as item (item.id)} 63 + <BaseCard {item}> 64 + <Card {item} /> 65 + </BaseCard> 66 + {/each} 67 + <div style="height: {(maxHeight / 8) * 100}cqw;"></div> 68 + {/if} 64 69 </div> 65 70 </div> 66 71