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
10 changes: 5 additions & 5 deletions backend/pnpm-lock.yaml

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

9 changes: 6 additions & 3 deletions backend/src/modules/iam/iam.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,10 @@ export class IamService {
* Membuat inisial nama dengan desain premium & gradasi warna yang dinamis
*/
function generateSvgAvatar(name: string): string {
const initial = name ? name.trim().charAt(0).toUpperCase() : '?';
const MAX_NAME_LENGTH = 128;
const safeName =
typeof name === 'string' ? name.trim().slice(0, MAX_NAME_LENGTH) : '';
const initial = safeName ? safeName.charAt(0).toUpperCase() : '?';

// Daftar warna gradasi premium yang modern dan estetis
const gradients = [
Expand All @@ -168,8 +171,8 @@ function generateSvgAvatar(name: string): string {

// Hitung hash deterministik dari nama agar pengguna yang sama selalu mendapat gradasi warna yang sama
let hash = 0;
for (let i = 0; i < name.length; i++) {
hash = name.charCodeAt(i) + ((hash << 5) - hash);
for (let i = 0; i < safeName.length; i++) {
hash = safeName.charCodeAt(i) + ((hash << 5) - hash);
}
const index = Math.abs(hash) % gradients.length;
const { start, end } = gradients[index];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,27 @@ export function ListingDigitalProductStep() {
}
};

const isGoogleDrive = listingData.digitalLink.toLowerCase().includes("drive.google.com") ||
listingData.digitalLink.toLowerCase().includes("docs.google.com");

const isDropbox = listingData.digitalLink.toLowerCase().includes("dropbox.com");
const hasAllowedHost = (url: string, allowedHosts: string[]) => {
try {
const hostname = new URL(url).hostname.toLowerCase();
return allowedHosts.some((allowedHost) => {
const normalizedAllowedHost = allowedHost.toLowerCase();
return (
hostname === normalizedAllowedHost ||
hostname.endsWith(`.${normalizedAllowedHost}`)
);
});
} catch {
return false;
}
};

const isGoogleDrive = hasAllowedHost(listingData.digitalLink, [
"drive.google.com",
"docs.google.com",
]);

const isDropbox = hasAllowedHost(listingData.digitalLink, ["dropbox.com"]);

return (
<div className="space-y-5 animate-in fade-in slide-in-from-right-4 duration-300">
Expand Down
45 changes: 32 additions & 13 deletions frontend/app/features/orders/components/OrderDetailView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -141,19 +141,38 @@ export function OrderDetailView({ orderId }: OrderDetailViewProps) {
</a>
)}

{order.listing.digitalLink && (
<a
href={order.listing.digitalLink.startsWith("http") ? order.listing.digitalLink : `https://${order.listing.digitalLink}`}
target="_blank"
rel="noopener noreferrer"
className="flex-1 inline-flex items-center justify-center gap-2.5 px-5 py-3.5 rounded-sm border border-border bg-background text-foreground font-bold hover:bg-muted transition-all text-xs shadow-sm cursor-pointer"
>
<ExternalLink className="h-4 w-4 shrink-0" />
{order.listing.digitalLink.includes("drive.google.com") || order.listing.digitalLink.includes("docs.google.com")
? "Buka Tautan Google Drive"
: "Akses Tautan Eksternal"}
</a>
)}
{order.listing.digitalLink && (() => {
const externalHref = order.listing.digitalLink.startsWith("http")
? order.listing.digitalLink
: `https://${order.listing.digitalLink}`;

let externalHost = "";
try {
externalHost = new URL(externalHref).hostname.toLowerCase();
} catch {
externalHost = "";
}

const isGoogleDocsOrDrive =
externalHost === "drive.google.com" ||
externalHost.endsWith(".drive.google.com") ||
externalHost === "docs.google.com" ||
externalHost.endsWith(".docs.google.com");

return (
<a
href={externalHref}
target="_blank"
rel="noopener noreferrer"
className="flex-1 inline-flex items-center justify-center gap-2.5 px-5 py-3.5 rounded-sm border border-border bg-background text-foreground font-bold hover:bg-muted transition-all text-xs shadow-sm cursor-pointer"
>
<ExternalLink className="h-4 w-4 shrink-0" />
{isGoogleDocsOrDrive
? "Buka Tautan Google Drive"
: "Akses Tautan Eksternal"}
</a>
);
})()}
</div>
) : (
<div className="p-4 border border-border bg-muted/30 rounded-sm space-y-2">
Expand Down
Loading