Skip to content

Commit c48bbca

Browse files
committed
feat(i18n): add contact section with details and form labels in English
1 parent 0d75b9b commit c48bbca

2 files changed

Lines changed: 96 additions & 0 deletions

File tree

src/i18n/en.ts

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,46 @@ const en = {
499499
},
500500
severity: { alta: 'high', media: 'medium' },
501501
},
502+
contact: {
503+
title: 'Contact — CodeByMike',
504+
description: "Get in touch to talk about your project or a collaboration.",
505+
eyebrow: 'Intake',
506+
h1: "Tell me what you're building.",
507+
intro: "I can help you scale your product, review your architecture, or build from scratch. First response in under 24 hours.",
508+
bullets: [
509+
'Full-stack projects, architecture, performance, and technical consulting.',
510+
'I respond within 24 hours, Monday to Friday.',
511+
'Colombia · GMT−5 · Available for global remote work.',
512+
],
513+
scheduleCta: 'Schedule a call ↗',
514+
scheduleDetail: '30 minutes via Calendly, no form needed.',
515+
directContact: 'Direct contact',
516+
whatsappLabel: 'WhatsApp',
517+
linkedinLabel: 'LinkedIn ↗',
518+
downloadCv: 'Download CV',
519+
form: {
520+
badge: 'Form',
521+
fieldCount: '{n}/{total} fields',
522+
nameLabel: 'Name',
523+
namePlaceholder: 'Your name',
524+
emailLabel: 'Email',
525+
emailPlaceholder: 'you@email.com',
526+
subjectLabel: 'Subject',
527+
subjectPlaceholder: 'What is your project about?',
528+
messageLabel: 'Message',
529+
messagePlaceholder: "Tell me what you're building, where you're stuck, or what you need.",
530+
tlsNote: 'Sent over TLS',
531+
submitCta: 'Send message',
532+
okShort: '✓ Ok',
533+
nameTooShort: '✗ Minimum 2 characters',
534+
emailInvalid: '✗ Invalid email',
535+
messageCharCount: '✓ {n} chars',
536+
messageTooShort: '✗ {n}/{min} min.',
537+
successStatus: "✓ Message sent. I'll reply within 24 hours.",
538+
errorStatus: '✗ Error sending. Please try again.',
539+
networkErrorStatus: '✗ Network error. Please try again.',
540+
},
541+
},
502542
} satisfies typeof es
503543

504544
export default en

tests/bpmn.test.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,62 @@ describe('findLayoutIssues', () => {
251251
expect(issues.some((i) => i.kind === 'crossing')).toBe(true)
252252
})
253253

254+
it('detecta una etiqueta de rama posada sobre el trazo de otra flecha', () => {
255+
const issues = findLayoutIssues({
256+
...base,
257+
lanes: [
258+
{ id: 'a', label: '' },
259+
{ id: 'b', label: '' },
260+
],
261+
nodes: [
262+
{ id: 'g', type: 'gatewayExclusive', label: '', lane: 'a', col: 0 },
263+
{ id: 'x', type: 'task', label: 'X', lane: 'a', col: 1 },
264+
{ id: 'y', type: 'task', label: 'Y', lane: 'b', col: 1 },
265+
{ id: 'z', type: 'task', label: 'Z', lane: 'b', col: 0 },
266+
],
267+
// z → x sube por el mismo corredor donde g etiqueta su rama hacia y.
268+
flows: [
269+
{ from: 'g', to: 'y', label: 'una etiqueta bien ancha' },
270+
{ from: 'g', to: 'x', label: 'otra' },
271+
{ from: 'z', to: 'x' },
272+
],
273+
})
274+
expect(issues.some((i) => i.kind === 'label')).toBe(true)
275+
})
276+
277+
it('detecta una etiqueta de nodo aterrizando sobre la figura de al lado', () => {
278+
const issues = findLayoutIssues({
279+
...base,
280+
nodes: [
281+
// El texto de un evento cuelga debajo; con la tarea justo en la fila
282+
// siguiente, cae dentro de su caja.
283+
{ id: 'e', type: 'startEvent', label: 'Una etiqueta larga de evento', lane: 'l', col: 0 },
284+
{ id: 't', type: 'task', label: 'T', lane: 'l', col: 0, row: 1 },
285+
],
286+
flows: [{ from: 'e', to: 't' }],
287+
})
288+
expect(issues.some((i) => i.detail.includes('cae sobre la figura'))).toBe(true)
289+
})
290+
291+
it('detecta un texto que se sale del lienzo', () => {
292+
const issues = findLayoutIssues({
293+
...base,
294+
nodes: [
295+
{
296+
id: 'a',
297+
type: 'task',
298+
label: 'A',
299+
lane: 'l',
300+
col: 0,
301+
duracion: 'una anotación de tiempo absurdamente larga que no cabe',
302+
},
303+
{ id: 'b', type: 'task', label: 'B', lane: 'l', col: 1 },
304+
],
305+
flows: [{ from: 'a', to: 'b' }],
306+
})
307+
expect(issues.some((i) => i.detail.includes('se sale del lienzo'))).toBe(true)
308+
})
309+
254310
it('detecta la etiqueta de una rama encimada con la de su compuerta', () => {
255311
const gwAbajo = findLayoutIssues({
256312
...base,

0 commit comments

Comments
 (0)