diff --git a/frontend/src/data/cellDivisionStages.ts b/frontend/src/data/cellDivisionStages.ts index 26c283e..2dd5712 100644 --- a/frontend/src/data/cellDivisionStages.ts +++ b/frontend/src/data/cellDivisionStages.ts @@ -312,3 +312,126 @@ export const MEIOSIS_STAGES: Stage[] = [ ], }, ]; + +// ======================= ERROS: NÃO-DISJUNÇÃO ============================ +// A maioria das síndromes de aneuploidia (Down, Turner, Klinefelter...) +// vem de um par de cromossomos que deixa de se separar — os DOIS vão +// pro MESMO polo em vez de um pra cada. Aqui isolamos exatamente o +// momento em que isso acontece, contrastando com a separação normal (ver +// GENETIC_SYNDROMES em geneticSyndromes.ts pras síndromes de verdade). + +// ---- Não-disjunção na Meiose I (homólogos B e C não se separam) -------- +// Diferença importante pro erro na Meiose II: como o erro acontece ANTES +// da citocinese I, ele se propaga pras DUAS células — depois da Meiose II +// (não animada aqui, mas explicada no texto), os 4 gametas finais saem +// TODOS anormais (2 com um cromossomo a mais, 2 com um a menos). +export const MEIOSIS_I_ERROR_STAGES: Stage[] = [ + { + id: "metaf1-erro", + label: "Metáfase I", + description: + "Ponto de partida normal: as tétrades (pares de homólogos) alinhadas na placa metafásica, cada uma presa a fibras do fuso vindas dos dois polos.", + cells: [{ center: [0, 0, 0], radius: R, envelope: 0, spindle: true, elongated: 0 }], + chromatids: [ + ...pair("b1a", "b1b", COLOR_B, 0, [-0.27, 0, 0]), + ...pair("c1a", "c1b", COLOR_C, 0, [-0.13, 0, 0]), + ...pair("y1a", "y1b", COLOR_Y, 0, [0.13, 0, 0]), + ...pair("o1a", "o1b", COLOR_O, 0, [0.27, 0, 0]), + ], + }, + { + id: "anaf1-erro", + label: "Anáfase I — não-disjunção", + description: + "Erro: o par de homólogos azul/ciano NÃO se separa (falha na fibra do fuso ou no ponto de checagem) e os dois inteiros são puxados pro MESMO polo, enquanto o par laranja/amarelo se separa normalmente.", + cells: [{ center: [0, 0, 0], radius: R, envelope: 0, spindle: true, elongated: 0.4 }], + chromatids: [ + ...pair("b1a", "b1b", COLOR_B, 0, [POLE, 0.16, 0.05]), + ...pair("c1a", "c1b", COLOR_C, 0, [POLE, -0.16, -0.05]), + ...pair("y1a", "y1b", COLOR_Y, 0, [-POLE, 0, 0.05]), + ...pair("o1a", "o1b", COLOR_O, 0, [POLE + 0.32, 0, -0.05]), + ], + }, + { + id: "cito1-erro", + label: "Telófase I + Citocinese I — resultado", + description: + "As 2 células já nascem desiguais: uma fica com um cromossomo A MENOS (só o amarelo — vai virar um gameta n-1, monossômico), a outra com um A MAIS (azul + ciano + laranja — vai virar um gameta n+1, trissômico). A Meiose II segue normal a partir daqui, então TODOS os 4 gametas finais saem anormais (2 monossômicos, 2 trissômicos) — bem diferente de um erro na Meiose II.", + cells: [ + { center: [-FINAL_POLE, 0, 0], radius: 0.62, envelope: 0.7, spindle: false, elongated: 0 }, + { center: [FINAL_POLE, 0, 0], radius: 0.62, envelope: 0.7, spindle: false, elongated: 0 }, + ], + chromatids: [ + ...pair("y1a", "y1b", COLOR_Y, 0, [0, 0, 0]), + ...pair("b1a", "b1b", COLOR_B, 1, [-0.13, 0.1, 0.05]), + ...pair("c1a", "c1b", COLOR_C, 1, [-0.13, -0.1, -0.05]), + ...pair("o1a", "o1b", COLOR_O, 1, [0.15, 0, 0]), + ], + }, +]; + +// ---- Não-disjunção na Meiose II (cromátides-irmãs do azul não separam) -- +// Parte do resultado NORMAL da Meiose I (2 células haploides, cada +// cromossomo ainda duplicado). O erro acontece só numa das 2 células — +// por isso só 2 dos 4 gametas finais saem anormais, os outros 2 (que vêm +// da célula sem erro) ficam perfeitamente normais. +export const MEIOSIS_II_ERROR_STAGES: Stage[] = [ + { + id: "metaf2-erro", + label: "Metáfase II", + description: + "Ponto de partida normal (já depois da Meiose I): cada uma das 2 células haploides alinha seus cromossomos duplicados na própria placa metafásica.", + cells: [ + { center: [-FINAL_POLE, 0, 0], radius: 0.62, envelope: 0, spindle: true, elongated: 0 }, + { center: [FINAL_POLE, 0, 0], radius: 0.62, envelope: 0, spindle: true, elongated: 0 }, + ], + chromatids: [ + ...pair("b1a", "b1b", COLOR_B, 0, [-0.16, 0, 0]), + ...pair("y1a", "y1b", COLOR_Y, 0, [0.16, 0, 0]), + ...pair("c1a", "c1b", COLOR_C, 1, [-0.16, 0, 0]), + ...pair("o1a", "o1b", COLOR_O, 1, [0.16, 0, 0]), + ], + }, + { + id: "anaf2-erro", + label: "Anáfase II — não-disjunção (célula da esquerda)", + description: + "Na célula da ESQUERDA, as duas cromátides-irmãs do cromossomo azul não se separam e vão juntas pro mesmo polo (o amarelo se separa normal). A célula da DIREITA se divide inteiramente normal — o erro fica isolado numa célula só.", + cells: [ + { center: [-FINAL_POLE, 0, 0], radius: 0.62, envelope: 0, spindle: true, elongated: 0.4 }, + { center: [FINAL_POLE, 0, 0], radius: 0.62, envelope: 0, spindle: true, elongated: 0.4 }, + ], + chromatids: [ + single("b1a", COLOR_B, 0, [-0.4, 0.1, 0.04], 0), + single("b1b", COLOR_B, 0, [-0.4, -0.05, -0.04], 170), + single("y1a", COLOR_Y, 0, [-0.4, -0.2, 0], 10), + single("y1b", COLOR_Y, 0, [0.4, 0.1, 0], 170), + single("c1a", COLOR_C, 1, [-0.4, 0.1, 0], 20), + single("o1a", COLOR_O, 1, [-0.4, -0.1, 0], -15), + single("c1b", COLOR_C, 1, [0.4, -0.1, 0], 160), + single("o1b", COLOR_O, 1, [0.4, 0.1, 0], 195), + ], + }, + { + id: "cito2-erro", + label: "Telófase II + Citocinese II — resultado", + description: + "4 gametas ao final: os dois da ESQUERDA saem anormais — um trissômico (2 cópias do azul + 1 amarelo) e um monossômico (só 1 amarelo, faltando o azul); os dois da DIREITA (vindos da célula que não teve erro) saem completamente normais. Metade dos gametas afetados, metade normais — a marca registrada de um erro na Meiose II.", + cells: [ + { center: [-1.8, 0, 0], radius: 0.5, envelope: 0.9, spindle: false, elongated: 0 }, + { center: [-0.6, 0, 0], radius: 0.5, envelope: 0.9, spindle: false, elongated: 0 }, + { center: [0.6, 0, 0], radius: 0.5, envelope: 0.9, spindle: false, elongated: 0 }, + { center: [1.8, 0, 0], radius: 0.5, envelope: 0.9, spindle: false, elongated: 0 }, + ], + chromatids: [ + single("b1a", COLOR_B, 0, [0, 0.1, 0.04], 0), + single("b1b", COLOR_B, 0, [0, -0.05, -0.04], 170), + single("y1a", COLOR_Y, 0, [0, -0.2, 0], 10), + single("y1b", COLOR_Y, 1, [0, 0, 0], 170), + single("c1a", COLOR_C, 2, [0, 0.08, 0], 20), + single("o1a", COLOR_O, 2, [0, -0.08, 0], -15), + single("c1b", COLOR_C, 3, [0, 0.08, 0], 160), + single("o1b", COLOR_O, 3, [0, -0.08, 0], 195), + ], + }, +]; diff --git a/frontend/src/data/geneticSyndromes.ts b/frontend/src/data/geneticSyndromes.ts new file mode 100644 index 0000000..d715bb1 --- /dev/null +++ b/frontend/src/data/geneticSyndromes.ts @@ -0,0 +1,113 @@ +// Síndromes causadas por erros na divisão celular — dados de referência +// (não depende de nenhum dataset 3D, só texto curado). Duas famílias de +// erro bem diferentes, por isso separamos: +// - "não-disjunção": um par de cromossomos (homólogos, na Meiose I, ou +// cromátides-irmãs, na Meiose II — ou mais raramente na mitose, depois +// da fecundação) deixa de se separar e vai inteiro pra um único polo. +// Resultado: um gameta/célula com um cromossomo A MAIS (n+1) e outro +// com um a MENOS (n-1) — a causa da maioria das síndromes de aneuploidia. +// - "estrutural": o cromossomo se quebra e um PEDAÇO é perdido, duplicado +// ou trocado de lugar — o número de cromossomos continua normal, o que +// muda é a quantidade/organização de genes num deles. +export type ErrorMechanism = + | "meiose1" + | "meiose2" + | "mitose-pos-zigoto" + | "estrutural"; + +export interface GeneticSyndrome { + id: string; + namePt: string; + karyotype: string; + mechanism: ErrorMechanism; + originNote: string; + description: string; +} + +export const ERROR_MECHANISM_LABELS: Record = { + meiose1: "Não-disjunção na Meiose I", + meiose2: "Não-disjunção na Meiose II", + "mitose-pos-zigoto": "Não-disjunção mitótica (pós-fecundação)", + estrutural: "Aberração cromossômica estrutural", +}; + +export const GENETIC_SYNDROMES: GeneticSyndrome[] = [ + { + id: "down", + namePt: "Síndrome de Down", + karyotype: "Trissomia do 21 (47,XX ou XY,+21)", + mechanism: "meiose1", + originNote: + "~95% dos casos vêm de não-disjunção — na maioria das vezes na Meiose I materna (o risco sobe muito com a idade da mãe, porque os ovócitos ficam \"pausados\" em Prófase I por décadas). O restante vem de translocação robertsoniana (cromossomo 14 grudado no 21) ou de mosaicismo pós-zigótico.", + description: + "Deficiência intelectual de grau variável, hipotonia muscular, características faciais típicas (olhos com prega epicântica, face achatada), e maior risco de cardiopatia congênita e problemas de tireoide.", + }, + { + id: "turner", + namePt: "Síndrome de Turner", + karyotype: "Monossomia do X (45,X0)", + mechanism: "meiose1", + originNote: + "Perda de um cromossomo sexual — em boa parte dos casos o cromossomo perdido é de origem PATERNA (não-disjunção no espermatozoide), mas também ocorre por não-disjunção materna ou por perda mitótica pós-zigótica (gerando mosaicismo 45,X/46,XX).", + description: + "Afeta só meninas (XY sem o segundo cromossomo sexual não é viável). Baixa estatura, ausência ou desenvolvimento incompleto dos ovários (geralmente infertilidade), pescoço alado; a inteligência costuma ser normal.", + }, + { + id: "klinefelter", + namePt: "Síndrome de Klinefelter", + karyotype: "47,XXY", + mechanism: "meiose1", + originNote: + "Não-disjunção dos cromossomos sexuais, tanto na Meiose I quanto na Meiose II — de origem materna ou paterna em proporções parecidas. É a aneuploidia de cromossomo sexual mais comum em homens.", + description: + "Testículos pequenos e baixa produção de testosterona (geralmente infertilidade), estatura alta, e em alguns casos ginecomastia e dificuldades de aprendizado leves — muitos casos nunca chegam a ser diagnosticados.", + }, + { + id: "edwards", + namePt: "Síndrome de Edwards", + karyotype: "Trissomia do 18 (47,+18)", + mechanism: "meiose2", + originNote: + "Não-disjunção materna, mais frequentemente na Meiose II (diferente da trissomia do 21, onde a Meiose I predomina) — também associada à idade materna avançada.", + description: + "Quadro grave: malformações múltiplas (cardíacas, renais), punhos cerrados com dedos sobrepostos, baixo peso ao nascer. A maioria dos bebês não sobrevive ao primeiro ano de vida.", + }, + { + id: "patau", + namePt: "Síndrome de Patau", + karyotype: "Trissomia do 13 (47,+13)", + mechanism: "meiose1", + originNote: "Não-disjunção materna (Meiose I na maioria dos casos), também associada à idade materna avançada.", + description: + "Também grave: fenda labial/palatina, polidactilia (dedos extras), malformações cerebrais e cardíacas importantes. Sobrevida além do primeiro ano é rara.", + }, + { + id: "triplo-x", + namePt: "Síndrome do Triplo X", + karyotype: "47,XXX", + mechanism: "meiose1", + originNote: "Não-disjunção materna, na Meiose I ou na Meiose II.", + description: + "A maioria das mulheres com esse cariótipo tem desenvolvimento físico e fertilidade normais, muitas vezes sem nunca ser diagnosticada; algumas apresentam estatura um pouco acima da média e dificuldades de aprendizado leves.", + }, + { + id: "jacobs", + namePt: "Síndrome de Jacobs", + karyotype: "47,XYY", + mechanism: "meiose2", + originNote: + "Sempre de origem PATERNA — as duas cromátides-irmãs do cromossomo Y (já duplicado) deixam de se separar na Meiose II, gerando um espermatozoide com dois Y.", + description: + "Estatura acima da média; a maioria dos homens com esse cariótipo tem desenvolvimento e fertilidade normais e nunca é diagnosticada.", + }, + { + id: "cri-du-chat", + namePt: "Síndrome do Miado do Gato (Cri-du-chat)", + karyotype: "Deleção parcial do braço curto do cromossomo 5 (46,XX ou XY,5p-)", + mechanism: "estrutural", + originNote: + "Diferente das anteriores: aqui o NÚMERO de cromossomos continua normal (46) — um pedaço do cromossomo 5 se perde por quebra cromossômica durante a formação dos gametas (ocasionalmente por mitose no embrião inicial), não por não-disjunção.", + description: + "Recebe esse nome pelo choro do bebê, agudo e semelhante ao miado de um gato (por alteração na laringe). Causa deficiência intelectual, microcefalia e atraso no desenvolvimento.", + }, +]; diff --git a/frontend/src/routes/CellDivisionPage.tsx b/frontend/src/routes/CellDivisionPage.tsx index cce848c..1872560 100644 --- a/frontend/src/routes/CellDivisionPage.tsx +++ b/frontend/src/routes/CellDivisionPage.tsx @@ -1,32 +1,97 @@ -import { useEffect, useState } from "react"; +import { useEffect, useMemo, useState } from "react"; import { Canvas } from "@react-three/fiber"; import { CameraControls } from "@react-three/drei"; import { CellDivisionScene } from "../components/cellDivision/CellDivisionScene.js"; -import { MITOSIS_STAGES, MEIOSIS_STAGES } from "../data/cellDivisionStages.js"; +import { + MITOSIS_STAGES, + MEIOSIS_STAGES, + MEIOSIS_I_ERROR_STAGES, + MEIOSIS_II_ERROR_STAGES, +} from "../data/cellDivisionStages.js"; +import { GENETIC_SYNDROMES, ERROR_MECHANISM_LABELS, type ErrorMechanism } from "../data/geneticSyndromes.js"; -type Mode = "mitose" | "meiose"; +type Mode = "mitose" | "meiose" | "erros"; +type ErrorType = "meiose1" | "meiose2"; const AUTOPLAY_MS = 3200; +function SyndromeCard({ mechanism, compact }: { mechanism?: ErrorMechanism; compact?: boolean }) { + const list = mechanism ? GENETIC_SYNDROMES.filter((s) => s.mechanism === mechanism) : GENETIC_SYNDROMES; + return ( +
+ {list.map((s) => ( +
+
+

{s.namePt}

+ {s.karyotype} +
+ {!compact && ( + + {ERROR_MECHANISM_LABELS[s.mechanism]} + + )} +

{s.originNote}

+

{s.description}

+
+ ))} +
+ ); +} + +function SyndromeModal({ onClose }: { onClose: () => void }) { + return ( +
+
e.stopPropagation()} + > +
+

Síndromes genéticas — visão geral

+ +
+

+ A maioria vem de não-disjunção (um par de cromossomos que não se separa — ver as animações desta página); a última é um exemplo de{" "} + aberração estrutural (perda de um pedaço do cromossomo), um mecanismo diferente. +

+ +
+
+ ); +} + export default function CellDivisionPage() { const [mode, setMode] = useState("mitose"); + const [errorType, setErrorType] = useState("meiose1"); const [stageIndex, setStageIndex] = useState(0); const [playing, setPlaying] = useState(false); const [leftOpen, setLeftOpen] = useState(false); const [rightOpen, setRightOpen] = useState(false); + const [showSyndromeModal, setShowSyndromeModal] = useState(false); - const stages = mode === "mitose" ? MITOSIS_STAGES : MEIOSIS_STAGES; + const stages = useMemo(() => { + if (mode === "mitose") return MITOSIS_STAGES; + if (mode === "meiose") return MEIOSIS_STAGES; + return errorType === "meiose1" ? MEIOSIS_I_ERROR_STAGES : MEIOSIS_II_ERROR_STAGES; + }, [mode, errorType]); const stage = stages[stageIndex]; - // Trocar de modo reinicia o estágio — misturar índice de mitose (7 - // estágios) com o array de meiose (9 estágios) fora de ordem não faz - // sentido pedagogicamente. + // Trocar de modo (ou, dentro de "erros", de tipo de não-disjunção) + // reinicia o estágio — misturar o índice de uma sequência com o array + // de outra não faz sentido pedagogicamente. function changeMode(next: Mode) { setMode(next); setStageIndex(0); setPlaying(false); } + function changeErrorType(next: ErrorType) { + setErrorType(next); + setStageIndex(0); + setPlaying(false); + } + function goTo(index: number) { setStageIndex(Math.max(0, Math.min(stages.length - 1, index))); } @@ -87,13 +152,41 @@ export default function CellDivisionPage() { Meiose +

- {mode === "mitose" - ? "1 célula (2n=4, simplificado) → 2 células-filhas idênticas." - : "1 célula (2n=4) → 4 células-filhas haploides, geneticamente diferentes entre si."} + {mode === "mitose" && "1 célula (2n=4, simplificado) → 2 células-filhas idênticas."} + {mode === "meiose" && "1 célula (2n=4) → 4 células-filhas haploides, geneticamente diferentes entre si."} + {mode === "erros" && "O que acontece quando um par de cromossomos deixa de se separar — a origem da maioria das síndromes de aneuploidia."}

+ {mode === "erros" && ( +
+

Onde o erro ocorre

+
+ + +
+
+ )} +

Fases

    @@ -121,6 +214,15 @@ export default function CellDivisionPage() { ))}
+ + {mode === "erros" && ( + + )} {(leftOpen || rightOpen) && ( @@ -206,12 +308,25 @@ export default function CellDivisionPage() { > ✕ Fechar - - {mode === "mitose" ? "Mitose" : "Meiose"} + + {mode === "mitose" && "Mitose"} + {mode === "meiose" && "Meiose"} + {mode === "erros" && `Erro na ${ERROR_MECHANISM_LABELS[errorType]}`}

{stage.label}

{stage.description}

+ {mode === "erros" && ( +
+

Síndromes ligadas a este erro

+ +
+ )} +

Legenda das cores

@@ -236,6 +351,8 @@ export default function CellDivisionPage() { Modelo ilustrativo e simplificado (2n=4 em vez dos 46 cromossomos humanos reais) — pensado pra mostrar os conceitos-chave de cada fase, não uma simulação biofísica exata. Arraste pra girar, role pra dar zoom.

+ + {showSyndromeModal && setShowSyndromeModal(false)} />}
); } diff --git a/frontend/tsconfig.tsbuildinfo b/frontend/tsconfig.tsbuildinfo index 9bcc0b6..b4aed43 100644 --- a/frontend/tsconfig.tsbuildinfo +++ b/frontend/tsconfig.tsbuildinfo @@ -1 +1 @@ -{"root":["./src/app.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/celldiagram3d.tsx","./src/components/clippingcontrols.tsx","./src/components/cookieconsent.tsx","./src/components/feedbackwidget.tsx","./src/components/layertoggle.tsx","./src/components/layout.tsx","./src/components/microscopydiagram.tsx","./src/components/onlinecounter.tsx","./src/components/quickregionnav.tsx","./src/components/searchnav.tsx","./src/components/skindiagram3d.tsx","./src/components/structureinfopanel.tsx","./src/components/celldivision/celldivisionscene.tsx","./src/components/viewer/exammarkers.tsx","./src/components/viewer/mannequin.tsx","./src/components/viewer/scene.tsx","./src/components/viewer/systemmodel.tsx","./src/data/celldivisionstages.ts","./src/data/microscopycredits.ts","./src/data/microscopyhotspots.ts","./src/data/musclereferenceimages.ts","./src/data/physicalexam.ts","./src/hooks/usestructures.ts","./src/hooks/usesystemstructures.ts","./src/lib/analytics.ts","./src/lib/api.ts","./src/routes/adminstatspage.tsx","./src/routes/atlaspage.tsx","./src/routes/celldivisionpage.tsx","./src/routes/physicalexampage.tsx","./src/routes/planespage.tsx","./src/routes/quizpage.tsx","./src/store/useatlasstore.ts"],"version":"5.9.3"} \ No newline at end of file +{"root":["./src/app.tsx","./src/main.tsx","./src/vite-env.d.ts","./src/components/celldiagram3d.tsx","./src/components/clippingcontrols.tsx","./src/components/cookieconsent.tsx","./src/components/feedbackwidget.tsx","./src/components/layertoggle.tsx","./src/components/layout.tsx","./src/components/microscopydiagram.tsx","./src/components/onlinecounter.tsx","./src/components/quickregionnav.tsx","./src/components/searchnav.tsx","./src/components/skindiagram3d.tsx","./src/components/structureinfopanel.tsx","./src/components/celldivision/celldivisionscene.tsx","./src/components/viewer/exammarkers.tsx","./src/components/viewer/mannequin.tsx","./src/components/viewer/scene.tsx","./src/components/viewer/systemmodel.tsx","./src/data/celldivisionstages.ts","./src/data/geneticsyndromes.ts","./src/data/microscopycredits.ts","./src/data/microscopyhotspots.ts","./src/data/musclereferenceimages.ts","./src/data/physicalexam.ts","./src/hooks/usestructures.ts","./src/hooks/usesystemstructures.ts","./src/lib/analytics.ts","./src/lib/api.ts","./src/routes/adminstatspage.tsx","./src/routes/atlaspage.tsx","./src/routes/celldivisionpage.tsx","./src/routes/physicalexampage.tsx","./src/routes/planespage.tsx","./src/routes/quizpage.tsx","./src/store/useatlasstore.ts"],"version":"5.9.3"} \ No newline at end of file