00 / 05

RD Saúde: Apps Drogasil & Droga Raia
Equipo CORE de las apps de Drogasil y Droga Raia, en funcionalidades críticas para conversión y experiencia de usuario.
React Native, TypeScript, GraphQL, Node.js (BFF), MVVM, SOLID
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);
const flash = document.getElementById('flash');
let x = innerWidth * .5, y = innerHeight * .38;
let tx = x, ty = y;
const loop = () => {
x += (tx - x) * .14;
y += (ty - y) * .14;
flash.style.setProperty('--mx', x + 'px');
flash.style.setProperty('--my', y + 'px');
requestAnimationFrame(loop);
};
addEventListener('pointermove', e => {
tx = e.clientX;
ty = e.clientY;
}, { passive: true });
// sem ponteiro fino, a luz desce com a pagina
addEventListener('scroll', () => {
if (matchMedia('(pointer: fine)').matches) return;
const max = docEl.scrollHeight - innerHeight;
ty = innerHeight * (.2 + (scrollY / max) * .6);
}, { passive: true });
requestAnimationFrame(loop);Del código a la producción: construyo experiencias web y móviles que llegan a las manos de quien las usa.
Brasil
Trabajo en producto que ya era grande cuando llegué: código mío corre en apps de farmacia, de escuela, de banco digital y de salud.
Mi terreno es React Native y React con TypeScript, de la arquitectura a la entrega, pasando por code review, BFF, GraphQL y la parte aburrida que nadie publica: pruebas, build roto y bug en producción a las seis de la tarde.
Me gusta una interfaz bien resuelta y una decisión técnica que alguien pueda defender seis meses después. Escribo pensando en quien va a mantenerlo.

01 / 07
Proyectos en los que contribuí con desarrollo frontend y mobile
01 / 06
00 / 05

Equipo CORE de las apps de Drogasil y Droga Raia, en funcionalidades críticas para conversión y experiencia de usuario.
React Native, TypeScript, GraphQL, Node.js (BFF), MVVM, SOLID
01 / 05

Tres frentes a la vez: app del estudiante, app de la escuela y la biblioteca de componentes.
React Native, TypeScript, Jest, Storybook, Component Library, Testes Automatizados
02 / 05

Un backoffice en Next.js que jubiló la hoja de cálculo.
React, Next.js, TypeScript, Tailwind CSS, SCSS, NextAuth, Keycloak
03 / 05

Sitio institucional y app Android de una plataforma de salud digital.
React, React Native, JavaScript, TypeScript, APIs REST, Web & Mobile Integration
04 / 05

App interna de fuerza de ventas en React Native y TypeScript.
React Native, TypeScript, Redux, Context API, Jest, CI/CD, Azure DevOps
05 / 05

Microfrontends aplicados al móvil, que es donde la idea se complica.
React Native, Expo, TypeScript, Microfrontends, Componentização, Design System
Herramientas y tecnologías que utilizo en el desarrollo
¿Trabajemos juntos?
iniciando erika.lopes
idioma es
montando interfaz
listo