your-projects-section.svelte
1 <script lang="ts" context="module"> 2 export const PROJECTS_SECTION_PROJECT_FRAGMENT = gql` 3 ${PROJECT_CARD_FRAGMENT} 4 fragment ProjectsSectionProject on Project { 5 ...ProjectCard 6 } 7 `; 8 </script> 9 10 <script lang="ts"> 11 import PrimaryColorThemer from '../primary-color-themer/primary-color-themer.svelte'; 12 import ProjectCard, { PROJECT_CARD_FRAGMENT } from '../project-card/project-card.svelte'; 13 import Box from '$lib/components/icons/Box.svelte'; 14 import Section from '../section/section.svelte'; 15 import { gql } from 'graphql-request'; 16 import type { ProjectsSectionProjectFragment } from './__generated__/gql.generated'; 17 import isClaimed from '$lib/utils/project/is-claimed'; 18 import Plus from '../icons/Plus.svelte'; 19 import filterCurrentChainData from '$lib/utils/filter-current-chain-data'; 20 import VisibilityToggle from '../visibility-toggle/visibility-toggle.svelte'; 21 import checkIsUser from '$lib/utils/check-is-user'; 22 import walletStore from '$lib/stores/wallet/wallet.store'; 23 import launchClaimProject from '$lib/utils/launch-claim-project'; 24 25 export let projects: ProjectsSectionProjectFragment[]; 26 export let withClaimProjectButton = false; 27 export let showVisibilityToggle = false; 28 export let label = 'Your projects'; 29 30 let error = false; 31 32 export let collapsed = false; 33 export let collapsable = false; 34 35 let showHidden: boolean = false; 36 $: hiddenProjectsCount = projects.filter((p) => !p.isVisible).length ?? 0; 37 38 $: visibleProjects = projects.filter((p) => p.isVisible); 39 40 $: hiddenProjects = showHidden ? projects.filter((p) => !p.isVisible) : []; 41 42 $: isOwner = $walletStore.connected && checkIsUser(projects[0]?.chainData[0]?.owner?.accountId); 43 </script> 44 45 <Section 46 bind:collapsed 47 bind:collapsable 48 header={{ 49 icon: Box, 50 label, 51 actions: withClaimProjectButton 52 ? [ 53 { 54 label: 'Claim project', 55 icon: Plus, 56 handler: () => launchClaimProject(), 57 }, 58 ] 59 : [], 60 }} 61 skeleton={{ 62 horizontalScroll: false, 63 loaded: true, 64 empty: showVisibilityToggle ? projects.length === 0 : visibleProjects.length === 0, 65 error, 66 emptyStateEmoji: '🫙', 67 emptyStateHeadline: 'No claimed projects', 68 emptyStateText: withClaimProjectButton 69 ? 'If you develop an open-source project, click "Claim project" to get started.' 70 : 'This user hasnʼt claimed any software projects yet.', 71 disconnected: !$walletStore.connected, 72 disconnectedStateEmoji: '🫙', 73 disconnectedStateHeadline: 'Connect your wallet', 74 disconnectedStateText: 'Your claimed projects will show up here when your wallet is connected.', 75 }} 76 > 77 {#if visibleProjects} 78 <div class="projects"> 79 {#each visibleProjects as project} 80 {@const projectChainData = filterCurrentChainData(project.chainData)} 81 {#if isClaimed(projectChainData)} 82 <div> 83 <PrimaryColorThemer colorHex={projectChainData.color}> 84 <ProjectCard {project} isHidden={!project.isVisible} /> 85 </PrimaryColorThemer> 86 </div> 87 {/if} 88 {/each} 89 </div> 90 {/if} 91 92 {#if isOwner && showVisibilityToggle} 93 <VisibilityToggle bind:showHidden hiddenItemsCount={hiddenProjectsCount} /> 94 {/if} 95 96 <div class="projects"> 97 {#each hiddenProjects as project} 98 {@const projectChainData = filterCurrentChainData(project.chainData)} 99 {#if isClaimed(projectChainData)} 100 <div> 101 <PrimaryColorThemer colorHex={projectChainData.color}> 102 <ProjectCard {project} isHidden={!project.isVisible} /> 103 </PrimaryColorThemer> 104 </div> 105 {/if} 106 {/each} 107 </div> 108 </Section> 109 110 <style> 111 .projects { 112 display: flex; 113 gap: 1rem; 114 max-width: 100%; 115 position: relative; 116 padding: 2px; 117 flex-wrap: wrap; 118 } 119 120 .projects > * { 121 width: calc(50% - 0.5rem); 122 } 123 124 @media (max-width: 560px) { 125 .projects > * { 126 width: 100%; 127 max-width: 100%; 128 } 129 } 130 </style>