Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@creit.tech/stellar-wallets-kit": "^1.5.0",
"@radix-ui/react-dialog": "^1.1.15",
"@radix-ui/react-label": "^2.1.8",
"@radix-ui/react-popover": "^1.1.15",
"@radix-ui/react-separator": "^1.1.8",
"@radix-ui/react-slot": "^1.2.4",
"@radix-ui/react-tooltip": "^1.2.8",
Expand Down
1 change: 1 addition & 0 deletions src/@types/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@ export type CredentialTemplate = {
description: string;
vcType: string;
fields: TemplateField[];
iconSrc?: string;
};
14 changes: 14 additions & 0 deletions src/app/dashboard/notifications/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { NotificationList } from '@/components/modules/notifications/ui/NotificationList';

export const metadata = {
title: 'Notifications',
};

export default function NotificationsPage() {
return (
<div className="space-y-6">
<h1 className="text-xl font-semibold text-zinc-100">Notifications</h1>
<NotificationList />
</div>
);
}
152 changes: 152 additions & 0 deletions src/components/modules/issue/hooks/useCredentialTemplates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export function useCredentialTemplates() {
title: 'Escrow',
description: 'Programmable escrow credential linked to Trustless Work.',
vcType: 'EscrowCredential',
iconSrc: '/tw.png',
fields: [
{
key: 'subject',
Expand All @@ -48,6 +49,7 @@ export function useCredentialTemplates() {
title: 'Contributions',
description: 'Contributions count to a specific project.',
vcType: 'ContributionsCredential',
iconSrc: '/gf.png',
fields: [
{
key: 'subject',
Expand Down Expand Up @@ -120,6 +122,156 @@ export function useCredentialTemplates() {
{ key: 'expirationDate', label: 'Expiration Date', type: 'date' },
],
},
{
id: 'event_attendance',
title: 'Event Attendance',
description: 'Credential for event or conference attendance.',
vcType: 'EventAttendanceCredential',
fields: [
{
key: 'subject',
label: 'Subject DID',
type: 'did',
required: true,
placeholder: 'Wallet (G...) – we derive DID',
},
{ key: 'eventName', label: 'Event Name', type: 'text', required: true },
{ key: 'eventDate', label: 'Event Date', type: 'date', required: true },
{ key: 'location', label: 'Location', type: 'text', required: true },
{ key: 'role', label: 'Role', type: 'text', required: false, placeholder: 'Attendee' },
{ key: 'organizer', label: 'Organizer', type: 'text', required: false },
{ key: 'issueDate', label: 'Issue Date', type: 'date', required: true },
{ key: 'expirationDate', label: 'Expiration Date', type: 'date' },
],
},
{
id: 'payment_receipt',
title: 'Payment Receipt',
description: 'Credential for payment or transaction receipts.',
vcType: 'PaymentReceiptCredential',
fields: [
{
key: 'subject',
label: 'Subject DID',
type: 'did',
required: true,
placeholder: 'Wallet (G...) – we derive DID',
},
{ key: 'merchant', label: 'Merchant', type: 'text', required: true },
{ key: 'invoiceId', label: 'Invoice ID', type: 'text', required: true },
{ key: 'amount', label: 'Amount', type: 'number', required: true },
{ key: 'asset', label: 'Asset', type: 'text', required: true, placeholder: 'USDC' },
{ key: 'paidAt', label: 'Payment Date', type: 'date', required: true },
{ key: 'txHash', label: 'Transaction Hash', type: 'text', required: false },
{ key: 'issueDate', label: 'Issue Date', type: 'date', required: true },
],
},
{
id: 'kyc_verification',
title: 'KYC Verification',
description: 'Identity verification credential.',
vcType: 'KYCVerificationCredential',
fields: [
{
key: 'subject',
label: 'Subject DID',
type: 'did',
required: true,
placeholder: 'Wallet (G...) – we derive DID',
},
{ key: 'fullName', label: 'Full Name', type: 'text', required: true },
{ key: 'country', label: 'Country', type: 'text', required: true },
{
key: 'verificationLevel',
label: 'Verification Level',
type: 'text',
required: true,
placeholder: 'Basic | Advanced | Full',
},
{ key: 'verifiedBy', label: 'Verified By', type: 'text', required: true },
{ key: 'issueDate', label: 'Issue Date', type: 'date', required: true },
{ key: 'expirationDate', label: 'Expiration Date', type: 'date' },
],
},
{
id: 'access_pass',
title: 'Access Pass',
description: 'Credential granting access to resources or services.',
vcType: 'AccessPassCredential',
fields: [
{
key: 'subject',
label: 'Subject DID',
type: 'did',
required: true,
placeholder: 'Wallet (G...) – we derive DID',
},
{ key: 'resource', label: 'Resource', type: 'text', required: true },
{
key: 'permission',
label: 'Permission',
type: 'text',
required: true,
placeholder: 'read | write | admin',
},
{ key: 'scope', label: 'Scope', type: 'text', required: false },
{ key: 'issueDate', label: 'Issue Date', type: 'date', required: true },
{ key: 'expirationDate', label: 'Expiration Date', type: 'date' },
],
},
{
id: 'skill_badge',
title: 'Skill Badge',
description: 'Credential recognizing a specific skill or competency.',
vcType: 'SkillBadgeCredential',
fields: [
{
key: 'subject',
label: 'Subject DID',
type: 'did',
required: true,
placeholder: 'Wallet (G...) – we derive DID',
},
{ key: 'skill', label: 'Skill', type: 'text', required: true },
{
key: 'level',
label: 'Level',
type: 'text',
required: true,
placeholder: 'Beginner | Intermediate | Expert',
},
{ key: 'issuer', label: 'Issuer', type: 'text', required: true },
{ key: 'evidenceUrl', label: 'Evidence URL', type: 'text', required: false },
{ key: 'issueDate', label: 'Issue Date', type: 'date', required: true },
],
},
{
id: 'warranty',
title: 'Warranty',
description: 'Product warranty or support credential.',
vcType: 'WarrantyCredential',
fields: [
{
key: 'subject',
label: 'Subject DID',
type: 'did',
required: true,
placeholder: 'Wallet (G...) – we derive DID',
},
{ key: 'productName', label: 'Product Name', type: 'text', required: true },
{ key: 'serialNumber', label: 'Serial Number', type: 'text', required: true },
{ key: 'purchaseDate', label: 'Purchase Date', type: 'date', required: true },
{
key: 'coverage',
label: 'Coverage',
type: 'text',
required: true,
placeholder: 'Full | Limited',
},
{ key: 'issueDate', label: 'Issue Date', type: 'date', required: true },
{ key: 'expirationDate', label: 'Expiration Date', type: 'date' },
],
},
];

const templates: CredentialTemplate[] = [...builtIn, ...customTemplates];
Expand Down
16 changes: 3 additions & 13 deletions src/components/modules/issue/ui/DynamicIssueForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,20 +87,10 @@ export default function DynamicIssueForm({
<h3 className="text-xl font-semibold text-white mb-2">
{template ? `Create credential ${template.title.toLowerCase()}` : 'Form'}
</h3>
{template?.id === 'escrow' && (
{template?.iconSrc && (
<Image
src="/tw.png"
alt="Escrow"
width={120}
height={120}
className="absolute top-4 right-4 w-24 h-24 object-contain"
priority={false}
/>
)}
{template?.id === 'contributions' && (
<Image
src="/gf.png"
alt="Contributions"
src={template.iconSrc}
alt={template.title}
width={120}
height={120}
className="absolute top-4 right-4 w-24 h-24 object-contain"
Expand Down
56 changes: 56 additions & 0 deletions src/components/modules/notifications/hooks/useNotificationToast.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
'use client';

import { useCallback } from 'react';
import { useRouter } from 'next/navigation';
import { toast } from 'sonner';
import type { Notification } from '../types';
import { NOTIFICATION_TYPE_LABEL } from '../types';

export function useNotificationToast() {
const router = useRouter();

const showNotificationToast = useCallback(
(notification: Notification) => {
const vcId = notification.metadata?.vc_id;
const action = vcId
? {
label: 'View credential' as const,
onClick: () => router.push(`/credential/${vcId}`),
}
: {
label: 'View all' as const,
onClick: () => router.push('/dashboard/notifications'),
};

const copy = NOTIFICATION_TYPE_LABEL[notification.type];
const title = copy?.title ?? 'Notification';
const description = copy?.message ?? notification.message;

switch (notification.type) {
case 'credential_received':
toast.success(title, { description, action });
break;
case 'credential_verified':
toast.info(title, { description, action });
break;
case 'credential_expiring_soon':
toast.info(title, { description, action });
break;
case 'credential_revoked':
toast.warning(title, { description, action });
break;
case 'issuer_authorized':
toast.info(title, { description, action });
break;
case 'issuer_revoked':
toast.info(title, { description, action });
break;
default:
toast(title, { description, action });
}
},
[router]
);

return { showNotificationToast };
}
Loading
Loading