mirror of
https://github.com/block-core/angor-hub-old.git
synced 2026-01-31 15:44:20 +01:00
218 lines
12 KiB
HTML
218 lines
12 KiB
HTML
<div class="flex min-w-0 flex-auto flex-col">
|
||
<!-- Header -->
|
||
<div class="dark relative flex-0 overflow-hidden bg-gray-800 px-4 py-8 sm:p-16">
|
||
<!-- Background -->
|
||
<svg class="pointer-events-none absolute inset-0" viewBox="0 0 960 540" width="100%" height="100%"
|
||
preserveAspectRatio="xMidYMax slice" xmlns="http://www.w3.org/2000/svg">
|
||
<g class="text-gray-700 opacity-25" fill="none" stroke="currentColor" stroke-width="100">
|
||
<circle r="234" cx="196" cy="23"></circle>
|
||
<circle r="234" cx="790" cy="491"></circle>
|
||
</g>
|
||
</svg>
|
||
<div class="relative z-10 flex flex-col items-center">
|
||
<h2 class="text-xl font-semibold">Explore Projects</h2>
|
||
<div class="mt-1 text-center text-4xl font-extrabold leading-tight tracking-tight sm:text-7xl">
|
||
What’s your next investment?
|
||
</div>
|
||
<div class="text-secondary mt-6 max-w-2xl text-center tracking-tight sm:text-2xl">
|
||
Check out our projects and find your next investment
|
||
opportunity.
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<!-- Main -->
|
||
<div class="p-6 sm:p-10">
|
||
<div class="mx-auto flex w-full max-w-xs flex-auto flex-col sm:max-w-5xl">
|
||
<!-- Filters -->
|
||
<div class="flex w-full max-w-xs flex-col items-center justify-between sm:max-w-none sm:flex-row">
|
||
<!-- Search bar with clear button -->
|
||
<div class="flex w-full items-center space-x-2 sm:w-auto">
|
||
<mat-form-field class="mt-4 w-full sm:w-80" [subscriptSizing]="'dynamic'"
|
||
(keyup.enter)="filterByQuery(query.value)">
|
||
<mat-icon matPrefix class="icon-size-5"
|
||
[svgIcon]="'heroicons_solid:magnifying-glass'"></mat-icon>
|
||
<input placeholder="Search ..." matInput #query />
|
||
</mat-form-field>
|
||
<!-- Clear search button -->
|
||
@if (showCloseSearchButton()) {
|
||
<button mat-icon-button color="warn" class="mt-4" (click)="resetSearch(query)">
|
||
<mat-icon [svgIcon]="'heroicons_solid:x-mark'"></mat-icon>
|
||
</button>
|
||
}
|
||
@if (!showCloseSearchButton()) {
|
||
<button mat-icon-button color="success" class="mt-4" (click)="filterByQuery(query.value)">
|
||
<mat-icon [svgIcon]="'heroicons_solid:magnifying-glass'"></mat-icon>
|
||
</button>
|
||
}
|
||
</div>
|
||
<!-- Toggle completed -->
|
||
<mat-slide-toggle class="mt-8 sm:ml-auto sm:mt-0" [color]="'primary'">
|
||
Hide completed
|
||
</mat-slide-toggle>
|
||
</div>
|
||
</div>
|
||
<div class="mx-auto flex w-full flex-auto flex-col sm:max-w-5xl">
|
||
<!-- Project Cards -->
|
||
<div class="mt-10 grid w-full min-w-0 grid-cols-1 gap-6 sm:grid-cols-1 md:grid-cols-1 lg:grid-cols-2">
|
||
<!-- Loop through projects and render cards -->
|
||
@for (project of projectDetails(); track $index) {
|
||
<angor-card class="filter-info flex w-full flex-col">
|
||
<div class="flex h-32">
|
||
<img class="object-cover" [src]="
|
||
project.banner ||
|
||
'/images/pages/profile/cover.jpg'
|
||
" alt="Card cover image"
|
||
onerror="this.onerror=null; this.src='/images/pages/profile/cover.jpg';"
|
||
alt="Card cover image" />
|
||
</div>
|
||
<div class="flex px-8">
|
||
<div class="bg-card -mt-12 rounded-full p-1">
|
||
<img class="h-24 w-24 rounded-full object-cover" [src]="
|
||
project.picture ||
|
||
'images/avatars/avatar-placeholder.png'
|
||
" onerror="this.onerror=null; this.src='/images/avatars/avatar-placeholder.png';"
|
||
alt="Project logo" />
|
||
</div>
|
||
</div>
|
||
<div class="flex flex-col px-8 pb-6 pt-4">
|
||
<div class="flex items-center justify-between">
|
||
<div class="min-w-0 flex-1">
|
||
<div *ngIf="
|
||
project.displayName || project.name
|
||
" class="truncate text-2xl font-semibold leading-tight" role="button"
|
||
(click)="goToProjectDetails(project)">
|
||
{{
|
||
project.displayName ||
|
||
project.nostrPubKey
|
||
}}
|
||
</div>
|
||
<div *ngIf="
|
||
!project.name &&
|
||
!project.displayName
|
||
" class="truncate text-2xl font-semibold leading-tight">
|
||
{{
|
||
project.displayName ||
|
||
project.nostrPubKey
|
||
}}
|
||
</div>
|
||
<div class="text-secondary mt-1 truncate leading-tight">
|
||
{{
|
||
project.about ||
|
||
'No description available'
|
||
}}
|
||
</div>
|
||
</div>
|
||
<div *ngIf="project.displayName || project.name"
|
||
class="absolute right-2 top-2 flex space-x-2">
|
||
<!-- Buttons -->
|
||
<div
|
||
class="flex h-10 w-10 items-center justify-center rounded-full border bg-white shadow-md">
|
||
<button mat-icon-button [routerLink]="[
|
||
'/chat',
|
||
project.nostrPubKey,
|
||
]">
|
||
<mat-icon class="icon-size-5" [svgIcon]="
|
||
'heroicons_outline:chat-bubble-left-right'
|
||
"></mat-icon>
|
||
</button>
|
||
</div>
|
||
<div
|
||
class="flex h-10 w-10 items-center justify-center rounded-full border bg-white shadow-md">
|
||
<button mat-icon-button (click)="
|
||
toggleBookmark(
|
||
project.nostrPubKey
|
||
)
|
||
">
|
||
<mat-icon class="icon-size-5" [svgIcon]="
|
||
(
|
||
bookmarks$ | async
|
||
)?.includes(
|
||
project.nostrPubKey
|
||
)
|
||
? 'heroicons_solid:bookmark'
|
||
: 'heroicons_outline:bookmark'
|
||
">
|
||
</mat-icon>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
<hr class="my-6 w-full border-t" />
|
||
|
||
<!-- projectDetails -->
|
||
<countdown-timer
|
||
[startDate]="project.startDate"
|
||
[expiryDate]="project.expiryDate"
|
||
class="mb-4">
|
||
</countdown-timer>
|
||
<div class="grid grid-cols-2 gap-4">
|
||
<div class="flex flex-col">
|
||
<span class="text-sm text-gray-500">Target Amount</span>
|
||
<span class="font-semibold">{{ project.targetAmount | number }} BTC</span>
|
||
</div>
|
||
<div class="flex flex-col">
|
||
<span class="text-sm text-gray-500">Start Date</span>
|
||
<span class="font-semibold">{{ project.startDate*1000 | date }}</span>
|
||
</div>
|
||
<div class="flex flex-col">
|
||
<span class="text-sm text-gray-500">Penalty Days</span>
|
||
<span class="font-semibold">{{ project.penaltyDays }} days</span>
|
||
</div>
|
||
<div class="flex flex-col">
|
||
<span class="text-sm text-gray-500">Expiry Date</span>
|
||
<span class="font-semibold">{{ project.expiryDate*1000 | date }}</span>
|
||
</div>
|
||
<div class="flex flex-col">
|
||
<span class="text-sm text-gray-500">Stages</span>
|
||
<span class="font-semibold">{{ project.stages?.length || 0 }}</span>
|
||
</div>
|
||
<div class="flex flex-col">
|
||
<span class="text-sm text-gray-500">Seeders</span>
|
||
<span class="font-semibold">{{ project.projectSeeders?.secretHashes?.length || 0 }}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
</angor-card>
|
||
}
|
||
</div>
|
||
@if (!loading() || initialLoadComplete()) {
|
||
@if (projectDetails().length === 0) {
|
||
<div class="flex flex-auto flex-col items-center justify-center bg-gray-100 dark:bg-transparent">
|
||
<mat-icon class="icon-size-24" [svgIcon]="'heroicons_outline:archive-box-x-mark'"></mat-icon>
|
||
<div class="text-secondary mt-4 text-2xl font-semibold tracking-tight">
|
||
No projects
|
||
</div>
|
||
</div>
|
||
}
|
||
}
|
||
|
||
@if (loading() && !initialLoadComplete()) {
|
||
<div class="flex flex-auto flex-col items-center justify-center">
|
||
<mat-progress-spinner mode="indeterminate" diameter="48"></mat-progress-spinner>
|
||
<div class="text-secondary mt-4 text-xl">
|
||
Loading projects...
|
||
</div>
|
||
</div>
|
||
}
|
||
|
||
@if (projectDetails().length > 0) {
|
||
<!-- Load More Button -->
|
||
<div class="mt-10 flex justify-center">
|
||
<button mat-raised-button color="primary"
|
||
class="bg-card text-gray-700 hover:bg-gray-200 dark:text-gray-300 dark:hover:bg-gray-700"
|
||
(click)="loadMoreProjects()" [disabled]="loading()">
|
||
{{ loading() ? 'Loading...' : 'Load More Projects' }}
|
||
</button>
|
||
</div>
|
||
}
|
||
|
||
@if (!loading() && errorMessage()) {
|
||
<div class="error-message">
|
||
{{ errorMessage() }}
|
||
</div>
|
||
}
|
||
</div>
|
||
</div>
|
||
</div>
|