diff --git a/apps/app/content/cv/cv.mdx b/apps/app/content/cv/cv.mdx index d2117ad4..fc6366b6 100644 --- a/apps/app/content/cv/cv.mdx +++ b/apps/app/content/cv/cv.mdx @@ -14,11 +14,11 @@ import Chip from '@mui/material/Chip'; import Typography from '@mui/material/Typography'; import { SkillBadge } from "@n8v/app/components/elements/shields-io/variants/skill-badge"; import { Connect } from "@n8v/app/components/elements/shields-io/variants/connect"; +import { CvSectionDivider } from "@n8v/app/components/fragments/cv-section-divider"; import Grid from '@mui/material/Unstable_Grid2'; import Link from '@mui/material/Link'; import PermIdentity from "./images/perm_identity.svg"; -import Cake from "./images/cake.svg"; import Gender from "./images/gender.svg"; import Github from "./images/github.svg"; import LinkedIn from "./images/linkedin.svg"; @@ -27,6 +27,12 @@ import Mail from "./images/mail.svg"; import Markdown from "./images/markdown.svg"; import Phone from "./images/phone.svg"; +export const Constants = { + logoLinkedIn: + "data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHdpZHRoPSIxNiIgaGVpZ2h0PSIxNiIgZmlsbD0iIzBBNjZDMiIgdmlld0JveD0iMCAwIDE2IDE2Ij4KPHBhdGggZD0iTTAgMS4xNDZDMCAuNTEzLjUyNiAwIDEuMTc1IDBoMTMuNjVDMTUuNDc0IDAgMTYgLjUxMyAxNiAxLjE0NnYxMy43MDhjMCAuNjMzLS41MjYgMS4xNDYtMS4xNzUgMS4xNDZIMS4xNzVDLjUyNiAxNiAwIDE1LjQ4NyAwIDE0Ljg1NHptNC45NDMgMTIuMjQ4VjYuMTY5SDIuNTQydjcuMjI1em0tMS4yLTguMjEyYy44MzcgMCAxLjM1OC0uNTU0IDEuMzU4LTEuMjQ4LS4wMTUtLjcwOS0uNTItMS4yNDgtMS4zNDItMS4yNDhTMi40IDMuMjI2IDIuNCAzLjkzNGMwIC42OTQuNTIxIDEuMjQ4IDEuMzI3IDEuMjQ4em00LjkwOCA4LjIxMlY5LjM1OWMwLS4yMTYuMDE2LS40MzIuMDgtLjU4Ni4xNzMtLjQzMS41NjgtLjg3OCAxLjIzMi0uODc4Ljg2OSAwIDEuMjE2LjY2MiAxLjIxNiAxLjYzNHYzLjg2NWgyLjQwMVY5LjI1YzAtMi4yMi0xLjE4NC0zLjI1Mi0yLjc2NC0zLjI1Mi0xLjI3NCAwLTEuODQ1LjctMi4xNjUgMS4xOTN2LjAyNWgtLjAxNmwuMDE2LS4wMjVWNi4xNjloLTIuNGMuMDMuNjc4IDAgNy4yMjUgMCA3LjIyNXoiLz4KPC9zdmc+Cg==", + yearsOfExperience: new Date().getFullYear() - 2018, +}; + @@ -72,11 +78,11 @@ import Phone from "./images/phone.svg"; - Open minded developer with 4+ years of comprehensive expertise in Web App - Development with willingness to learn and master Full-stack Development. I - take great care in the code quality, readability, automator, architecture of - the things I build. I'm also an open-source enthusiast and love to collaborate - with open-source community. + Open minded Full-stack developer with {Constants.yearsOfExperience}+ years of + comprehensive expertise in Web App Development with willingness to learn and + master Gen AI development. I take great care in the code quality, readability, + automator, architecture of the things I build. I'm also an open-source + enthusiast and love to collaborate with open-source community. @@ -94,25 +100,26 @@ import Phone from "./images/phone.svg"; - - + + - - + + - + + + - - - + - + + - - + + - - + + @@ -134,47 +141,58 @@ import Phone from "./images/phone.svg"; /> - - - ##### Work experience - - +##### Work experience + +**McKinsey & Company** + +- **Software Engineer II** + _2025 Apr - Present_ +- **Software Engineer I** + _2023 Nov - 2025 Apr_ +- **Junior Software Engineer** + _2022 Dec - 2023 Nov_ **Zalo** - **Senior Software Engineer** - _2021 Sep - Present_ + _2021 Sep - 2022 Nov_ - **Software Engineer** _2020 Apr - 2021 Sep_ - **Accociate Software Engineer** _2019 Jun - 2020 Apr_ -**SAP Labs Vietnam** +**SAP** - **Accociate Software Engineer** _2019 Jun - 2018 Sep_ - **Intern** _2018 Jan - 2019 Jun_ -##### Projects +##### Projects + +**MCP Browser Kit** +_A pair of MCP server and browser extension that enables AI assistants to interact with your local browsers_ + +- Building an open-source Model Context Protocol (MCP) server and browser extension system with TypeScript to bridge AI assistants and web browsers +- Developing cross-browser extensions supporting Chrome, Firefox, Safari, Brave, and Edge with different extension manifest versions (M2/M3) +- Creating seamless browser automation capabilities that allow AI assistants to interact with web pages and perform browser actions + +**MLR Acceleration App** +_A smart app that leverages AI to speed up Medical, Legal, and Regulatory (MLR) document reviews_ + +- Building a modern web app with Next.js to create an easy-to-use interface for MLR processes +- Creating interactive PDF viewing and annotation features for better document review + +**Housing Super Apps - Web & Mobile** +_A housing super app that allows users to acquire and maintain their properties_ + +- Designing and developing cross-platform mobile applications using React Native to deliver seamless user experiences +- Implementing comprehensive authentication flows and user management systems integrated with IAM infrastructure **Zalo - Web & PC** _Zalo is a popular cross-platform messaging, video call app and more_ @@ -186,17 +204,17 @@ _Zalo is a popular cross-platform messaging, video call app and more_ **SAP Analytics Cloud - KPI Plugin** _Analytics Cloud is a pluggable SaaS BI platform and KPI plugin is builder of KPIs_ -- Designing and configurating bundler to publising the project as a Plugin for SAP Analytics Cloud +- Designing and configuring bundler to publishing the project as a Plugin for SAP Analytics Cloud - Developing and writing test for new features as a part of the plugin **SAP HANA Cockpit - Analytics Builder** _Analytics Builder is a graphical SQL design studio to enable flexible queries on top of tables_ - Implementing Grunt task to transpile & minify that helps speed up project development and improve the load time of the web app -- Developing new and cutomizing existing features using UI5 +- Developing new and customizing existing features using UI5 **Open Bucket** -_Open Bucket is an incognito P2P storage system, users are paid etherum if they share their disk space with others_ +_Open Bucket is an incognito P2P storage system, users are paid Ethereum if they share their disk space with others_ - Developing Desktop app with React, Redux, Electron - Developing Daemon, a service on the user's machine that interacts with Tracker and smart contracts, built with NodeJs, web3.js @@ -209,7 +227,7 @@ _A combination of e-commerce website and vending machines, these components comm - Developing a single page web app for admin and customer with Angular 2 - Developing and build a simple vending machine with Arduino and other hardwares -##### Achievements +##### Achievements **Certificate Of Agile Software Development With Scrum** _Axon Active Vietnam - 2016_ @@ -220,15 +238,15 @@ _Microsoft Vietnam - 2015_ **2ND Prize App Studio** _Ton Duc Thang University & Microsoft Vietnam - 2014_ -##### Education +##### Education **BSc in Computer Science** _Ton Duc Thang University, Ho Chi Minh - 2018_ -##### Contact info +##### Contact info {"Nguyễn Duy Thanh"} - - - {"ndthanhdev@outlook.com"} - - - - - {"Male"} - - - - - {"District 7, Ho Chi Minh, Vietnam"} - - - - - {"1996"} - - - - - - - + + + {"ndthanhdev@outlook.com"} + + + + + {"Male"} + + + + + {"Ho Chi Minh, Vietnam"} + + + + ( sUrl += leftText ? `${leftText}-` : "-"; sUrl += rightText ? `${rightText}-` : "-"; sUrl += encodeURIComponent(rightBg); + logo && (sUrl += `?logo=${logo}`); /* * FIXME: support other extensions @@ -65,17 +66,10 @@ export const ShieldsIO = React.forwardRef( const url = new URL(sUrl); - logo && url.searchParams.append("logo", logo); logoColor && url.searchParams.append("logoColor", logoColor); logoWidth && url.searchParams.append("logoWidth", logoWidth.toString()); - - // Url.searchParams.set("label", leftText); leftBg && url.searchParams.append("labelColor", leftBg); - // Url.searchParams.append("color", rightBg); - - // RightText && url.searchParams.set("message", rightText); - url.searchParams.append("style", shieldStyle); return url.toString(); diff --git a/apps/app/src/components/fragments/app-drawer/index.tsx b/apps/app/src/components/fragments/app-drawer/index.tsx index 08babbc4..0e8c3da7 100644 --- a/apps/app/src/components/fragments/app-drawer/index.tsx +++ b/apps/app/src/components/fragments/app-drawer/index.tsx @@ -1,4 +1,3 @@ -import { css } from "@emotion/react"; import CloseIcon from "@mui/icons-material/Close"; import DarkModeIcon from "@mui/icons-material/DarkModeOutlined"; import LightModeIcon from "@mui/icons-material/LightModeOutlined"; @@ -30,7 +29,7 @@ export const AppDrawer = ({ }: AppDrawerProps) => ( - + Settings diff --git a/apps/app/src/components/fragments/cv-section-divider/index.tsx b/apps/app/src/components/fragments/cv-section-divider/index.tsx new file mode 100644 index 00000000..09c0c656 --- /dev/null +++ b/apps/app/src/components/fragments/cv-section-divider/index.tsx @@ -0,0 +1,25 @@ +import Divider from "@mui/material/Divider"; +import Stack from "@mui/material/Stack"; +import { type ReactNode } from "react"; + +import { styles } from "./styles"; + +export interface CvSectionDividerProps { + children?: ReactNode; +} + +export const CvSectionDivider = ({ children }: CvSectionDividerProps) => { + return ( + + + {children} + + + ); +}; diff --git a/apps/app/src/components/fragments/cv-section-divider/styles.ts b/apps/app/src/components/fragments/cv-section-divider/styles.ts new file mode 100644 index 00000000..9ab683fa --- /dev/null +++ b/apps/app/src/components/fragments/cv-section-divider/styles.ts @@ -0,0 +1,11 @@ +import { css } from "@emotion/react"; + +export const styles = { + divider: css({ + width: "100%", + }), + + stack: css({ + width: "100%", + }), +}; diff --git a/apps/app/src/providers/mdx-provider.tsx b/apps/app/src/providers/mdx-provider.tsx index b3f56135..a4218dc9 100644 --- a/apps/app/src/providers/mdx-provider.tsx +++ b/apps/app/src/providers/mdx-provider.tsx @@ -1,12 +1,11 @@ import "prismjs/themes/prism-okaidia.css"; - -import type { AppTheme } from "@n8v/app/theme"; - import { MDXProvider } from "@mdx-js/react"; import Link from "@mui/material/Link"; import Typography from "@mui/material/Typography"; import * as React from "react"; +import { styles } from "./mdx-provider/styles"; + export type AppMDXProviderProps = React.PropsWithChildren; /* eslint-disable @typescript-eslint/no-explicit-any */ @@ -23,36 +22,19 @@ const text = (props: any) => ; const strong = (props: any) => ( ({ - fontWeight: theme.typography.fontWeightBold, - })} + css={styles.strong} variant="body1" {...props} /> ); const p = (props: any) => ( - ({ - marginBlockEnd: theme.spacing(1), - })} - paragraph - variant="body1" - /> + ); -const ul = (props: any) => ( -
    ({ - marginBlockEnd: theme.spacing(2), - marginBlockStart: theme.spacing(0), - })} - /> -); +const ul = (props: any) =>
      ; -const li = (props: any) =>
    • ; +const li = (props: any) =>
    • ; const a = (props: any) => ; diff --git a/apps/app/src/providers/mdx-provider/styles.ts b/apps/app/src/providers/mdx-provider/styles.ts new file mode 100644 index 00000000..6926e17b --- /dev/null +++ b/apps/app/src/providers/mdx-provider/styles.ts @@ -0,0 +1,22 @@ +import { css } from "@emotion/react"; +import { type AppTheme } from "@n8v/app/theme"; + +export const styles = { + li: css({}), + + p: (theme: AppTheme) => + css({ + marginBlockEnd: theme.spacing(1), + }), + + strong: (theme: AppTheme) => + css({ + fontWeight: theme.typography.fontWeightBold, + }), + + ul: (theme: AppTheme) => + css({ + marginBlockEnd: theme.spacing(2), + marginBlockStart: theme.spacing(0), + }), +};