Merge branch 'main' into feat/complete-en-th-translations

Risolve i conflitti su codice-etico mantenendo traduzioni EN/TH, companyConfig e link agli allegati.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Javaxman
2026-07-31 14:36:35 +02:00
6 changed files with 1572 additions and 1 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2,9 +2,73 @@
* Codice etico — riferimenti a prodotti e domini **separati in dati**: * Codice etico — riferimenti a prodotti e domini **separati in dati**:
* aggiungere una riga a `productLines` e, se serve, un `ConformityBlock` in * aggiungere una riga a `productLines` e, se serve, un `ConformityBlock` in
* `conformityBlocks` senza riscrivere la pagina intera. * `conformityBlocks` senza riscrivere la pagina intera.
*
* ═══════════════════════════════════════════════════════════════════════════
* CONFIGURAZIONE SOCIETARIA — compilare per rendere effettivo il documento.
* ═══════════════════════════════════════════════════════════════════════════
*/ */
import type { SupportedLocale } from './home/navigation'; import type { SupportedLocale } from './home/navigation';
/**
* Dati societari da personalizzare.
* Una volta compilati, il Codice Etico è formalmente effettivo.
*/
export const companyConfig = {
/** Ragione sociale ufficiale (se diversa dal marchio NexStudio) */
officialName: 'NexStudio',
/** Sede legale */
headquarters: 'Bangkok, Thailandia',
/** Partita IVA / codice fiscale thailandese */
taxId: '[DA INSERIRE]',
/** Numero registrazione società */
registrationNumber: '[DA INSERIRE]',
/** Approvatore del Codice Etico */
approver: {
/** Organo che approva (es. "Amministratore Delegato") */
role: '[DA INSERIRE — es. Amministratore Delegato]',
/** Nome e cognome del firmatario */
fullName: '[DA INSERIRE]',
/** Data di approvazione effettiva */
approvalDate: '[DA INSERIRE — es. 21 aprile 2026]',
},
/** Responsabile aggiornamenti del Codice */
updateOwner: {
role: 'Legal & Compliance, con supporto di DPO e CISO',
},
/** Governance — nomi dei ruoli chiave */
roles: {
ceo: '[DA INSERIRE]',
cto: '[DA INSERIRE]',
ciso: '[DA INSERIRE]',
dpo: '[DA INSERIRE]',
legal: '[DA INSERIRE]',
hr: '[DA INSERIRE]',
ethicsCommittee: '[DA INSERIRE o "non ancora costituito"]',
},
/** Contatti email */
contacts: {
privacy: 'privacy@nexstudio.com',
security: 'security@nexstudio.com',
ethics: 'ethics@nexstudio.com',
legal: 'legal@nexstudio.com',
hr: 'hr@nexstudio.com',
},
/** Audit e revisione */
review: {
/** Frequenza revisione del Codice */
frequency: 'minimo annuale o a fronte di mutamenti rilevanti',
/** Data ultima revisione */
lastReviewDate: '[DA INSERIRE]',
/** Data prossima revisione prevista */
nextReviewDate: '[DA INSERIRE]',
},
};
export type ConformityBlock = { export type ConformityBlock = {
id: string; id: string;
anchorId: string; anchorId: string;
@ -109,7 +173,7 @@ type CodiceEticoLocale = {
intro: string; intro: string;
items: readonly string[]; items: readonly string[];
}; };
allegati: { title: string; items: readonly string[] }; allegati: { title: string; items: readonly string[]; linkLabel: string };
approvazione: { approvazione: {
title: string; title: string;
items: readonly LabeledItem[]; items: readonly LabeledItem[];
@ -540,6 +604,7 @@ const codiceEticoByLocale: Record<SupportedLocale, CodiceEticoLocale> = {
}, },
allegati: { allegati: {
title: '18. Allegati e moduli (inclusi)', title: '18. Allegati e moduli (inclusi)',
linkLabel: 'Scarica e consulta tutti i template operativi nella pagina dedicata →',
items: [ items: [
'Dichiarazione personale di adesione al Codice (da firmare in onboarding).', 'Dichiarazione personale di adesione al Codice (da firmare in onboarding).',
'Template NDA e clausole minime per fornitori e sub-processori.', 'Template NDA e clausole minime per fornitori e sub-processori.',
@ -1030,6 +1095,7 @@ const codiceEticoByLocale: Record<SupportedLocale, CodiceEticoLocale> = {
}, },
allegati: { allegati: {
title: '18. Annexes and forms (included)', title: '18. Annexes and forms (included)',
linkLabel: 'Download and browse all operational templates on the dedicated page →',
items: [ items: [
'Personal declaration of adhesion to the Code (to be signed at onboarding).', 'Personal declaration of adhesion to the Code (to be signed at onboarding).',
'NDA template and minimum clauses for vendors and sub-processors.', 'NDA template and minimum clauses for vendors and sub-processors.',
@ -1520,6 +1586,7 @@ const codiceEticoByLocale: Record<SupportedLocale, CodiceEticoLocale> = {
}, },
allegati: { allegati: {
title: '18. ภาคผนวกและแบบฟอร์ม (รวมอยู่)', title: '18. ภาคผนวกและแบบฟอร์ม (รวมอยู่)',
linkLabel: 'ดาวน์โหลดและเรียกดูเทมเพลตปฏิบัติการทั้งหมดในหน้าเฉพาะ →',
items: [ items: [
'ประกาศยอมรับประมวลส่วนบุคคล (ลงนามตอนปฐมนิเทศ)', 'ประกาศยอมรับประมวลส่วนบุคคล (ลงนามตอนปฐมนิเทศ)',
'เทมเพลต NDA และข้อสัญญาน้อยสุดสำหรับผู้ให้บริการและผู้ประมวลผลช่วง', 'เทมเพลต NDA และข้อสัญญาน้อยสุดสำหรับผู้ให้บริการและผู้ประมวลผลช่วง',

109
src/pages/allegati.astro Normal file
View File

@ -0,0 +1,109 @@
---
import SubpageLayout from '../layouts/SubpageLayout.astro';
import { getAllegatiCodiceEtico } from '../data/allegati-codice-etico';
const path = Astro.url.pathname;
const localeMatch = path.match(/^\/(en|th)(\/|$)/);
const currentLocale = (localeMatch?.[1] ?? 'it') as 'it' | 'en' | 'th';
const a = getAllegatiCodiceEtico(currentLocale);
const { page, allegati } = a;
const link = 'text-sky-400/90 underline-offset-2 hover:text-sky-300 hover:underline';
const isLabeledFields = (item: unknown): item is { label: string; fields: string[] } =>
typeof item === 'object' && item !== null && 'label' in item && 'fields' in item;
const isLabeledText = (item: unknown): item is { label: string; text: string } =>
typeof item === 'object' && item !== null && 'label' in item && 'text' in item;
---
<SubpageLayout
title={page.title}
description={page.description}
heading={page.heading}
lead={page.lead}
>
<p class="mb-8 text-sm">
<a class={link} href={`/${currentLocale === 'it' ? '' : currentLocale + '/'}codice-etico`}>
{page.backLabel}
</a>
</p>
<div class="space-y-16">
{
allegati.map((allegato) => (
<section id={allegato.id} class="scroll-mt-8">
<h2 class="border-b border-nx-border pb-2 text-xl font-bold text-nx-fg">
{allegato.heading}
</h2>
<p class="mt-1 text-sm text-nx-muted">{allegato.description}</p>
{allegato.intro ? (
<p class="mt-4 text-sm italic text-nx-muted/90">{allegato.intro}</p>
) : null}
<div class="mt-6 space-y-6">
{
allegato.sections.map((section) => (
<div>
{section.title ? (
<h3 class="mb-3 text-base font-semibold text-nx-fg">{section.title}</h3>
) : null}
{section.intro ? (
<p class="mb-3 text-sm text-nx-muted">{section.intro}</p>
) : null}
{Array.isArray(section.content) ? (
section.content.length > 0 && typeof section.content[0] === 'string' ? (
<ul class="list-disc space-y-1.5 pl-5 text-sm leading-relaxed sm:text-base">
{(section.content as string[]).map((item) => (
<li>{item}</li>
))}
</ul>
) : section.content.length > 0 && isLabeledFields(section.content[0]) ? (
<dl class="space-y-3">
{(section.content as { label: string; fields: string[] }[]).map((item) => (
<div class="border-l-2 border-nx-border pl-4">
<dt class="text-sm font-medium text-nx-fg">{item.label}</dt>
<dd class="mt-0.5 font-mono text-sm text-nx-muted">
{item.fields.join(' | ')}
</dd>
</div>
))}
</dl>
) : section.content.length > 0 && isLabeledText(section.content[0]) ? (
<dl class="space-y-3">
{(section.content as { label: string; text: string }[]).map((item) => (
<div class="border-l-2 border-nx-border pl-4">
<dt class="text-sm font-semibold text-nx-fg">{item.label}</dt>
<dd class="mt-0.5 text-sm leading-relaxed text-nx-muted">{item.text}</dd>
</div>
))}
</dl>
) : (
<p class="text-sm text-nx-muted">{String(section.content)}</p>
)
) : (
<p class="text-sm leading-relaxed sm:text-base">{String(section.content)}</p>
)}
{section.note ? (
<p class="mt-3 border-l-2 border-sky-500/30 pl-4 text-sm leading-relaxed text-nx-muted">
{section.note}
</p>
) : null}
</div>
))
}
</div>
{allegato.footer ? (
<p class="mt-8 border-t border-nx-border pt-4 text-sm text-nx-fg">
{allegato.footer}
</p>
) : null}
</section>
))
}
</div>
</SubpageLayout>

View File

@ -270,6 +270,11 @@ const isLabeled = (item: string | { label: string; text: string }): item is { la
</ul> </ul>
<h2 id="allegati">{c.allegati.title}</h2> <h2 id="allegati">{c.allegati.title}</h2>
<p class="mb-4 text-sm">
<a class={link} href={`/${currentLocale === 'it' ? '' : currentLocale + '/'}allegati`}>
{c.allegati.linkLabel}
</a>
</p>
<ul> <ul>
{c.allegati.items.map((item) => <li>{item}</li>)} {c.allegati.items.map((item) => <li>{item}</li>)}
</ul> </ul>

View File

@ -0,0 +1,5 @@
---
import Page from '../allegati.astro';
---
<Page />

View File

@ -0,0 +1,5 @@
---
import Page from '../allegati.astro';
---
<Page />