mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 12:18:11 +00:00
133 lines
3.6 KiB
TypeScript
133 lines
3.6 KiB
TypeScript
/** Matches backend pdf-generator A4 dimensions at 96 CSS px. */
|
|
export const PDF_PAGE_WIDTH_PX = 794;
|
|
export const PDF_PAGE_HEIGHT_PX = 1123;
|
|
|
|
export type LetterPageMarginsPx = {
|
|
top: number;
|
|
left: number;
|
|
right: number;
|
|
bottom: number;
|
|
};
|
|
|
|
export type LetterLanguage = "am" | "en";
|
|
|
|
export const DEFAULT_LETTER_PAGE_MARGINS_PX: LetterPageMarginsPx = {
|
|
top: 120,
|
|
left: 30,
|
|
right: 20,
|
|
bottom: 120,
|
|
};
|
|
|
|
export const CLOSING_ASSET_GAP_AFTER_SINCERELY_PX = 8;
|
|
export const ESTIMATED_SINCERELY_BLOCK_HEIGHT_PX = 28;
|
|
|
|
export type ClosingLayoutAnchor = "signatures" | "seal" | "stamp";
|
|
|
|
export type AbsoluteLayoutAnchor =
|
|
| ClosingLayoutAnchor
|
|
| "senderSignature"
|
|
| "senderStamp";
|
|
|
|
export function computeLetterContentAreaPx(
|
|
margins: LetterPageMarginsPx = DEFAULT_LETTER_PAGE_MARGINS_PX,
|
|
): { width: number; height: number } {
|
|
return {
|
|
width: Math.max(
|
|
1,
|
|
PDF_PAGE_WIDTH_PX - margins.left - margins.right,
|
|
),
|
|
height: Math.max(
|
|
1,
|
|
PDF_PAGE_HEIGHT_PX - margins.top - margins.bottom,
|
|
),
|
|
};
|
|
}
|
|
|
|
function ptToPx(pt: number): number {
|
|
return Math.round((pt * 96) / 72);
|
|
}
|
|
|
|
export function isClosingLayoutAnchor(
|
|
anchor: AbsoluteLayoutAnchor,
|
|
): anchor is ClosingLayoutAnchor {
|
|
return anchor === "signatures" || anchor === "seal" || anchor === "stamp";
|
|
}
|
|
|
|
export function estimateClosingBlockTopPx(
|
|
_margins: LetterPageMarginsPx = DEFAULT_LETTER_PAGE_MARGINS_PX,
|
|
): number {
|
|
return 480;
|
|
}
|
|
|
|
export function buildDefaultClosingAssetAnchors(
|
|
contentWidth: number,
|
|
language: LetterLanguage = "am",
|
|
): Record<ClosingLayoutAnchor, { top: number; left: number }> {
|
|
const sigWidth = ptToPx(96);
|
|
const sealWidth = 140;
|
|
const sigHeight = 50;
|
|
const gap = CLOSING_ASSET_GAP_AFTER_SINCERELY_PX;
|
|
const baseTop = ESTIMATED_SINCERELY_BLOCK_HEIGHT_PX + gap;
|
|
|
|
if (language === "en") {
|
|
const columnLeft = 0;
|
|
const sealLeft = columnLeft + sigWidth + gap;
|
|
return {
|
|
signatures: { top: baseTop, left: columnLeft },
|
|
seal: { top: baseTop - 12, left: sealLeft },
|
|
stamp: { top: baseTop + sigHeight + gap, left: columnLeft },
|
|
};
|
|
}
|
|
|
|
const sealLeft = contentWidth - sealWidth;
|
|
const columnLeft = sealLeft - gap - sigWidth;
|
|
return {
|
|
signatures: { top: baseTop, left: columnLeft },
|
|
seal: { top: baseTop - 12, left: sealLeft },
|
|
stamp: { top: baseTop + sigHeight + gap, left: columnLeft },
|
|
};
|
|
}
|
|
|
|
export function buildDefaultAbsoluteAnchors(
|
|
margins: LetterPageMarginsPx = DEFAULT_LETTER_PAGE_MARGINS_PX,
|
|
language: LetterLanguage = "am",
|
|
): Record<AbsoluteLayoutAnchor, { top: number; left: number }> {
|
|
const { width, height } = computeLetterContentAreaPx(margins);
|
|
const closing = buildDefaultClosingAssetAnchors(width, language);
|
|
|
|
return {
|
|
...closing,
|
|
senderSignature: {
|
|
top: Math.round(height * 0.12),
|
|
left: Math.round(width * 0.48),
|
|
},
|
|
senderStamp: {
|
|
top: Math.round(height * 0.12),
|
|
left: Math.round(width * 0.64),
|
|
},
|
|
};
|
|
}
|
|
|
|
export function migrateClosingAssetTopFromPageAbsolute(
|
|
top: number,
|
|
margins: LetterPageMarginsPx = DEFAULT_LETTER_PAGE_MARGINS_PX,
|
|
): number {
|
|
const { height } = computeLetterContentAreaPx(margins);
|
|
if (top <= height * 0.45) return top;
|
|
return top - estimateClosingBlockTopPx(margins);
|
|
}
|
|
|
|
export function closingAssetToCanvasTop(
|
|
top: number,
|
|
margins: LetterPageMarginsPx = DEFAULT_LETTER_PAGE_MARGINS_PX,
|
|
): number {
|
|
return top + estimateClosingBlockTopPx(margins);
|
|
}
|
|
|
|
export function closingAssetFromCanvasTop(
|
|
top: number,
|
|
margins: LetterPageMarginsPx = DEFAULT_LETTER_PAGE_MARGINS_PX,
|
|
): number {
|
|
return top - estimateClosingBlockTopPx(margins);
|
|
}
|