diff --git a/apps/ungdomsytelse-soknad/CHANGELOG.md b/apps/ungdomsytelse-soknad/CHANGELOG.md new file mode 100644 index 000000000..83ee9c8eb --- /dev/null +++ b/apps/ungdomsytelse-soknad/CHANGELOG.md @@ -0,0 +1,13 @@ +# @navikt/sif-demo-app + +## 0.1.1 + +### Patch Changes + +- Pakkeoppdateringer - minor-patch + +## 0.1.0 + +### Minor Changes + +- f677f10: Sette opp demo-app som kan brukes for å teste ut større POCs. diff --git a/apps/ungdomsytelse-soknad/CODEOWNERS b/apps/ungdomsytelse-soknad/CODEOWNERS new file mode 100644 index 000000000..bcf20cb3f --- /dev/null +++ b/apps/ungdomsytelse-soknad/CODEOWNERS @@ -0,0 +1 @@ +* @navikt/dusseldorf diff --git a/apps/ungdomsytelse-soknad/Dockerfile b/apps/ungdomsytelse-soknad/Dockerfile new file mode 100644 index 000000000..f2f65f277 --- /dev/null +++ b/apps/ungdomsytelse-soknad/Dockerfile @@ -0,0 +1,78 @@ +FROM node:20.12-alpine AS base + +ARG APP="ungdomsytelse-soknad" +ARG SERVER="server" + +ENV SCOPE=@navikt/ungdomsytelse-soknad + +RUN apk fix \ + && apk add --no-cache --update libc6-compat tini \ + && rm -rf /var/cache/apk/* + +RUN yarn global add turbo + +######################################### +# PREPARE DEPS FOR BUILD +######################################### + +FROM base AS prepare +WORKDIR /app +COPY ["package.json", ".yarnrc.yml", "yarn.lock", "turbo.json", "./"] +COPY [".yarn/releases/*", ".yarn/releases/"] +COPY packages packages +COPY apps apps +ARG SERVER +COPY ${SERVER} ${SERVER} +RUN find apps \! -name "package.json" -mindepth 2 -maxdepth 2 -print | xargs rm -rf +RUN find packages \! -name "package.json" -mindepth 2 -maxdepth 2 -print | xargs rm -rf +RUN find ${SERVER} \! -name "package.json" -mindepth 2 -maxdepth 2 -print | xargs rm -rf + +######################################### +# BUILDER IMAGE - INSTALL PACKAGES AND COPY SOURCE +######################################### + +FROM prepare AS installer +COPY --from=prepare /app ./ +RUN --mount=type=secret,id=PACKAGES_AUTH_TOKEN \ + PACKAGES_AUTH_TOKEN=$(cat /run/secrets/PACKAGES_AUTH_TOKEN) yarn +COPY . . + +######################################### +# BUILD SERVER +######################################### + +FROM installer AS server-build +ARG SERVER +WORKDIR /app/${SERVER} +RUN --mount=type=secret,id=PACKAGES_AUTH_TOKEN \ + PACKAGES_AUTH_TOKEN=$(cat /run/secrets/PACKAGES_AUTH_TOKEN) yarn build + + +######################################### +# Client +######################################### + +FROM installer AS client-build +WORKDIR /app +RUN --mount=type=secret,id=PACKAGES_AUTH_TOKEN \ + PACKAGES_AUTH_TOKEN=$(cat /run/secrets/PACKAGES_AUTH_TOKEN) yarn turbo run build --filter=${SCOPE} +RUN mv /app/apps/${APP}/dist /public + + +######################################### +# Server +######################################### +FROM base AS server +ARG SERVER +WORKDIR /app +COPY --from=server-build /app/${SERVER}/dist ./ +ENTRYPOINT ["/sbin/tini", "--"] + +######################################### +# App +######################################### +FROM server + +COPY --from=client-build /public ./public + +CMD ["node", "index.js"] diff --git a/apps/ungdomsytelse-soknad/README.md b/apps/ungdomsytelse-soknad/README.md new file mode 100644 index 000000000..c90f98c4d --- /dev/null +++ b/apps/ungdomsytelse-soknad/README.md @@ -0,0 +1,3 @@ +# Testapp for SIF + +Enkel applikasjon som brukes som POC ved større endringer i sif-brukerdialog diff --git "a/apps/ungdomsytelse-soknad/api-mock/data/s\303\270ker1/arbeidsgivere-mock.json" "b/apps/ungdomsytelse-soknad/api-mock/data/s\303\270ker1/arbeidsgivere-mock.json" new file mode 100644 index 000000000..dc67d6c18 --- /dev/null +++ "b/apps/ungdomsytelse-soknad/api-mock/data/s\303\270ker1/arbeidsgivere-mock.json" @@ -0,0 +1,29 @@ +{ + "organisasjoner": [ + { "navn": "SJOKKERENDE ELEKTRIKER", "organisasjonsnummer": "947064649", "ansattFom": "2002-04-20" } + ], + "frilansoppdrag": [ + { + "type": "type oppdrag", + "organisasjonsnummer": "991012133", + "navn": "Hurdal frilanssenter", + "ansattFom": "2022-01-01", + "ansattTom": "2022-01-15" + }, + { + "type": "type oppdrag", + "organisasjonsnummer": "991012134", + "navn": "Svandalen frilanssenter", + "ansattFom": "2022-01-01", + "ansattTom": "2022-01-15" + } + ], + "privatarbeidsgiver": [ + { + "navn": "Jon Jonsen", + "ansattFom": "2021-01-01", + "ansattTom": "2021-12-31", + "offentligIdent": "12345678910" + } + ] +} diff --git "a/apps/ungdomsytelse-soknad/api-mock/data/s\303\270ker1/barn-mock.json" "b/apps/ungdomsytelse-soknad/api-mock/data/s\303\270ker1/barn-mock.json" new file mode 100644 index 000000000..f2f0f8d84 --- /dev/null +++ "b/apps/ungdomsytelse-soknad/api-mock/data/s\303\270ker1/barn-mock.json" @@ -0,0 +1,19 @@ +{ + "barn": [ + { + "fornavn": "ALFABETISK", + "etternavn": "FAGGOTT", + "aktørId": "2811762539343", + "fødselsdato": "2019-06-08", + "fødselsnummer": "08861999573" + }, + { + "fornavn": "Barn", + "mellomnavn": "Barne", + "etternavn": "Barnesen", + "fødselsdato": "2020-04-20", + "aktørId": "123" + }, + { "fødselsdato": "2015-01-02", "fornavn": "Mock", "etternavn": "Mocknes", "aktørId": "2", "mellomnavn": "" } + ] +} diff --git "a/apps/ungdomsytelse-soknad/api-mock/data/s\303\270ker1/s\303\270ker-mock.json" "b/apps/ungdomsytelse-soknad/api-mock/data/s\303\270ker1/s\303\270ker-mock.json" new file mode 100644 index 000000000..70f748b17 --- /dev/null +++ "b/apps/ungdomsytelse-soknad/api-mock/data/s\303\270ker1/s\303\270ker-mock.json" @@ -0,0 +1,8 @@ +{ + "aktørId": "2320509955297", + "fødselsdato": "1995-06-02", + "fødselsnummer": "02869599259", + "fornavn": "PRESENTABEL", + "mellomnavn": null, + "etternavn": "HOFTE" +} diff --git a/apps/ungdomsytelse-soknad/api-mock/mock-server.cjs b/apps/ungdomsytelse-soknad/api-mock/mock-server.cjs new file mode 100644 index 000000000..b7316b05f --- /dev/null +++ b/apps/ungdomsytelse-soknad/api-mock/mock-server.cjs @@ -0,0 +1,188 @@ +/* eslint-disable no-console */ +const express = require('express'); +const helmet = require('helmet'); +const busboyCons = require('busboy'); +const os = require('os'); +const fs = require('fs'); +const cors = require('cors'); + +const server = express(); + +server.use(express.json()); +server.use( + helmet({ + contentSecurityPolicy: true, + crossOriginEmbedderPolicy: false, + crossOriginResourcePolicy: false, + }), +); + +server.use( + cors({ + origin: 'http://localhost:8080', + methods: ['GET', 'POST', 'DELETE', 'PUT', 'OPTIONS'], + allowedHeaders: ['content-type', 'X-Brukerdialog-Git-Sha', 'x_correlation_id'], + credentials: true, + }), +); +server.options('*', cors()); + +const MELLOMLAGRING_JSON = `${os.tmpdir()}/omsorgspengesoknad-mellomlagring.json`; + +const isJSON = (str) => { + try { + return JSON.parse(str) && !!str; + } catch (e) { + return false; + } +}; + +const writeFileAsync = async (path, text) => { + return new Promise((resolve, reject) => { + fs.writeFile(path, text, 'utf8', (err) => { + if (err) reject(err); + else resolve(); + }); + }); +}; + +const readFileSync = (path) => { + return fs.readFileSync(path, 'utf8'); +}; + +const existsSync = (path) => fs.existsSync(path); + +const mockPath = `${__dirname}/data`; +const soker = 'søker1'; + +const søkerFileName = `søker-mock.json`; +const barnFileName = `barn-mock.json`; +const arbeidsgivereFileName = `arbeidsgivere-mock.json`; +const innvilgetVedtakFileName = `innvilget-vedtak-mock.json`; +const ikkeInnvilgetVedtakFileName = `ikke-innvilget-vedtak-mock.json`; + +const readMockFile = (file, responseObject) => { + const filePath = `${mockPath}/${soker}/${file}`; + if (existsSync(filePath)) { + const body = readFileSync(filePath); + responseObject.send(JSON.parse(body)); + } else { + responseObject.send({}); + } +}; + +const startExpressServer = () => { + const port = process.env.PORT || 8099; + + server.get('/oppslag/soker', (req, res) => { + setTimeout(() => { + readMockFile(søkerFileName, res); + }, 250); + }); + + server.get('/oppslag/barn', (req, res) => { + setTimeout(() => { + readMockFile(barnFileName, res); + }, 250); + }); + + server.get('/oppslag/arbeidsgiver', (req, res) => { + setTimeout(() => { + readMockFile(arbeidsgivereFileName, res); + }, 250); + }); + + /** --- Send søknad ---------- */ + + server.post('/omsorgspenger-utvidet-rett/innsending', (req, res) => { + const body = req.body; + console.log('[POST] body', body); + setTimeout(() => { + res.sendStatus(200); + }, 2500); + }); + + const errorResponse = { + type: '/problem-details/invalid-request-parameters', + title: 'invalid-request-parameters', + status: 400, + detail: 'Requesten inneholder ugyldige paramtere.', + instance: 'about:blank', + invalid_parameters: [ + 'høyereRisikoForFraværBeskrivelse matcher ikke tilatt møønster: ^[\\p{Punct}\\p{L}\\p{M}\\p{N}\\p{Sc}\\p{Space}«»–§�\\u2018\\u2019\\u201a\\u201b\\u201c\\u201d\\u201e\\u201f\\u00b4\\u2026]*$', + ], + }; + server.post('/omsorgspenger-utvidet-rett/innsending-error', (req, res) => { + const body = req.body; + console.log('[POST] body', body); + setTimeout(() => { + res.status(400).send(errorResponse); + }, 100); + }); + + /** --- Vedlegg ---------- */ + + server.post('/vedlegg', (req, res) => { + res.set('Access-Control-Expose-Headers', 'Location'); + res.set('Location', 'nav.no'); + const busboy = busboyCons({ headers: req.headers }); + busboy.on('finish', () => { + res.writeHead(200, { + Location: 'http://localhost:8089/vedlegg/eyJraWQiOiIxIiwidHlwIjoiSldUIiwiYWxnIjoibm9uZSJ9.eyJqdG', + }); + res.end(); + }); + req.pipe(busboy); + }); + + server.delete('/vedlegg', (req, res) => { + res.sendStatus(200); + }); + + /** --- Mellomlagring ---------- */ + + server.get('/mellomlagring/OMSORGSPENGER_UTVIDET_RETT', (req, res) => { + if (existsSync(MELLOMLAGRING_JSON)) { + const body = readFileSync(MELLOMLAGRING_JSON); + res.send(JSON.parse(body)); + } else { + res.send({}); + } + }); + server.post('/mellomlagring/OMSORGSPENGER_UTVIDET_RETT', (req, res) => { + const body = req.body; + const jsBody = isJSON(body) ? JSON.parse(body) : body; + writeFileAsync(MELLOMLAGRING_JSON, JSON.stringify(jsBody, null, 2)); + res.sendStatus(200); + }); + server.put('/mellomlagring/OMSORGSPENGER_UTVIDET_RETT', (req, res) => { + const body = req.body; + const jsBody = isJSON(body) ? JSON.parse(body) : body; + writeFileAsync(MELLOMLAGRING_JSON, JSON.stringify(jsBody, null, 2)); + res.sendStatus(200); + }); + server.delete('/mellomlagring/OMSORGSPENGER_UTVIDET_RETT', (req, res) => { + writeFileAsync(MELLOMLAGRING_JSON, JSON.stringify({}, null, 2)); + res.sendStatus(200); + }); + + server.listen(port, () => { + console.log(`Express mock-api server listening on port: ${port}`); + }); + + /** --- Sjekk tidligere innvilget vedtak ---------- */ + + server.post('/k9-sak-innsyn-api/k9sak/omsorgsdager-kronisk-sykt-barn/har-gyldig-vedtak', (req, res) => { + const body = req.body; + console.log('[POST] body', body); + setTimeout(() => { + if (body.pleietrengendeAktørId === '2') { + readMockFile(innvilgetVedtakFileName, res); + } else { + readMockFile(ikkeInnvilgetVedtakFileName, res); + } + }, 2500); + }); +}; + +startExpressServer(); diff --git a/apps/ungdomsytelse-soknad/dev-server.cjs b/apps/ungdomsytelse-soknad/dev-server.cjs new file mode 100644 index 000000000..489df784b --- /dev/null +++ b/apps/ungdomsytelse-soknad/dev-server.cjs @@ -0,0 +1,98 @@ +const { createProxyMiddleware, fixRequestBody } = require('http-proxy-middleware'); +const { injectDecoratorServerSide } = require('@navikt/nav-dekoratoren-moduler/ssr/index.js'); +const express = require('express'); +const server = express(); +server.use(express.json()); +const path = require('path'); +const mustacheExpress = require('mustache-express'); +const compression = require('compression'); + +server.disable('x-powered-by'); + +server.use(compression()); + +require('dotenv').config(); +server.set('views', `${__dirname}`); +server.set('view engine', 'mustache'); +server.engine('html', mustacheExpress()); + +server.use((req, res, next) => { + res.removeHeader('X-Powered-By'); + res.set('X-Frame-Options', 'SAMEORIGIN'); + res.set('X-XSS-Protection', '1; mode=block'); + res.set('X-Content-Type-Options', 'nosniff'); + res.set('Referrer-Policy', 'no-referrer'); + res.set('Feature-Policy', "geolocation 'none'; microphone 'none'; camera 'none'"); + next(); +}); + +async function injectDecorator(filePath) { + return injectDecoratorServerSide({ + env: 'dev', + filePath, + params: { + enforceLogin: false, + simple: true, + }, + }); +} + +const startServer = async () => { + server.get('/health/isAlive', (req, res) => res.sendStatus(200)); + server.get('/health/isReady', (req, res) => res.sendStatus(200)); + + const indexHtmlPath = path.resolve(__dirname, 'index.html'); + + const htmlWithDecoratorInjected = await injectDecorator(indexHtmlPath); + + const renderedHtml = htmlWithDecoratorInjected.replaceAll( + '{{{APP_SETTINGS}}}', + JSON.stringify({ + APP_VERSION: `${process.env.APP_VERSION}`, + PUBLIC_PATH: `${process.env.PUBLIC_PATH}`, + }), + ); + + server.use( + '/rest', + createProxyMiddleware({ + target: 'http://localhost:8888/rest', + changeOrigin: true, + logger: console, + on: { + proxyReq: fixRequestBody, + }, + }), + ); + + const fs = require('fs'); + fs.writeFileSync(path.resolve(__dirname, 'index-decorated.html'), renderedHtml); + + const vite = await require('vite').createServer({ + root: __dirname, + server: { + middlewareMode: true, + port: 8080, + open: './index-decorated.html', + }, + }); + + server.get(/^\/(?!.*dist).*$/, (req, _res, next) => { + const fullPath = path.resolve(__dirname, decodeURIComponent(req.path.substring(1))); + const fileExists = fs.existsSync(fullPath); + + if ((!fileExists && !req.url.startsWith('/@')) || req.url === '/') { + req.url = '/index-decorated.html'; + } + next(); + }); + + server.use(vite.middlewares); + + const port = process.env.PORT || 8080; + server.listen(port, () => { + console.log(`App listening on port: ${port}`); + }); +}; + +startServer(); diff --git a/apps/ungdomsytelse-soknad/eslint.config.js b/apps/ungdomsytelse-soknad/eslint.config.js new file mode 100644 index 000000000..f0aee4dd8 --- /dev/null +++ b/apps/ungdomsytelse-soknad/eslint.config.js @@ -0,0 +1,3 @@ +import commonConfig from '@sif/eslint-config'; + +export default commonConfig; diff --git a/apps/ungdomsytelse-soknad/index.html b/apps/ungdomsytelse-soknad/index.html new file mode 100644 index 000000000..c9ed7d538 --- /dev/null +++ b/apps/ungdomsytelse-soknad/index.html @@ -0,0 +1,20 @@ + + + + + + + + Ungdomsytelse søknad + + + + + +
+ + + + \ No newline at end of file diff --git a/apps/ungdomsytelse-soknad/nais/dev-gcp.json b/apps/ungdomsytelse-soknad/nais/dev-gcp.json new file mode 100644 index 000000000..0d04963c0 --- /dev/null +++ b/apps/ungdomsytelse-soknad/nais/dev-gcp.json @@ -0,0 +1,29 @@ +{ + "app": "ungdomsytelse-soknad", + "namespace": "dusseldorf", + "team": "dusseldorf", + "ingresses": ["https://ungdomsytelse-soknad.intern.dev.nav.no"], + "livenessPath": "/internal/health/isAlive", + "readinessPath": "/internal/health/isReady", + "externalHosts": ["www.nav.no", "dekoratoren.ekstern.dev.nav.no"], + "accessPolicyOutApps": ["k9-brukerdialog-prosessering", "sif-innsyn-api", "k9-sak-innsyn-api"], + "minReplicas": 1, + "maxReplicas": 1, + "cluster": "dev-gcp", + "observabilityEnabled": "true", + "env": { + "APP_VERSION": "dev", + "ENV": "{path}", + "INNSYN_FRONTEND_PATH": "/api/sif-innsyn", + "INNSYN_API_SCOPE": "dev-gcp:dusseldorf:sif-innsyn-api", + "INNSYN_API_URL": "http://sif-innsyn-api", + "K9_SAK_INNSYN_FRONTEND_PATH": "/api/k9sak-innsyn", + "K9_SAK_INNSYN_API_SCOPE": "dev-gcp:dusseldorf:k9-sak-innsyn-api", + "K9_SAK_INNSYN_API_URL": "http://k9-sak-innsyn-api", + "K9_BRUKERDIALOG_PROSESSERING_FRONTEND_PATH": "/api/brukerdialog", + "K9_BRUKERDIALOG_PROSESSERING_API_SCOPE": "dev-gcp:dusseldorf:k9-brukerdialog-prosessering", + "K9_BRUKERDIALOG_PROSESSERING_API_URL": "http://k9-brukerdialog-prosessering", + "NPM_CONFIG_CACHE": "/tmp", + "PUBLIC_PATH": "/familie/sykdom-i-familien/soknad/ungdomsytelse-soknad" + } +} diff --git a/apps/ungdomsytelse-soknad/package.json b/apps/ungdomsytelse-soknad/package.json new file mode 100644 index 000000000..4d059de94 --- /dev/null +++ b/apps/ungdomsytelse-soknad/package.json @@ -0,0 +1,62 @@ +{ + "name": "@navikt/ungdomsytelse-soknad", + "type": "module", + "private": true, + "version": "0.1.1", + "scripts": { + "dev": "node ./dev-server.cjs", + "dev-api": "PORT=8089 node ./api-mock/mock-server.cjs", + "dev:vite": "vite", + "dev:debug": "vite --debug", + "build": "vite build --base=/familie/sykdom-i-familien/soknad/ungdomsytelse-soknad", + "check:types": "tsc --noemit", + "lint": "eslint", + "lint:fix": "eslint --fix" + }, + "dependencies": { + "@navikt/aksel-icons": "7.0.1", + "@navikt/ds-css": "7.0.1", + "@navikt/ds-react": "7.0.1", + "@navikt/ds-tailwind": "7.0.1", + "@navikt/nav-dekoratoren-moduler": "3.1.0", + "@navikt/sif-common": "*", + "@navikt/sif-common-core-ds": "*", + "@navikt/sif-common-soknad-ds": "*", + "@navikt/sif-common-ui": "*", + "clsx": "2.1.1", + "date-fns": "4.1.0", + "react": "18.3.1", + "react-dom": "18.3.1", + "react-hook-form": "7.53.0", + "zod": "3.23.8" + }, + "devDependencies": { + "@eslint/eslintrc": "3.1.0", + "@eslint/js": "9.11.0", + "@navikt/nav-dekoratoren-moduler": "2.1.6", + "@types/node": "22.5.5", + "@types/react": "18.3.8", + "@types/react-dom": "18.3.0", + "@typescript-eslint/parser": "8.6.0", + "@vitejs/plugin-react": "4.3.1", + "autoprefixer": "10.4.20", + "compression": "1.7.4", + "eslint": "9.11.0", + "eslint-plugin-prettier": "5.2.1", + "eslint-plugin-react": "7.36.1", + "eslint-plugin-simple-import-sort": "12.1.1", + "eslint-plugin-unicorn": "55.0.0", + "express": "4.21.0", + "http-proxy-middleware": "3.0.2", + "mustache-express": "^1.3.2", + "postcss-import": "16.1.0", + "postcss-styled-syntax": "0.6.4", + "prettier": "3.3.3", + "stylelint": "16.9.0", + "tailwindcss": "3.4.12", + "typescript": "5.6.2", + "typescript-eslint": "8.6.0", + "vite": "5.4.7", + "vite-plugin-checker": "0.8.0" + } +} diff --git a/apps/ungdomsytelse-soknad/postcss.config.cjs b/apps/ungdomsytelse-soknad/postcss.config.cjs new file mode 100644 index 000000000..f25794d73 --- /dev/null +++ b/apps/ungdomsytelse-soknad/postcss.config.cjs @@ -0,0 +1,7 @@ +module.exports = { + plugins: { + 'postcss-import': {}, + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/apps/ungdomsytelse-soknad/src/App.tsx b/apps/ungdomsytelse-soknad/src/App.tsx new file mode 100644 index 000000000..7e1bf8154 --- /dev/null +++ b/apps/ungdomsytelse-soknad/src/App.tsx @@ -0,0 +1,52 @@ +import { Box, Tabs } from '@navikt/ds-react'; +import LoadingSpinner from '@navikt/sif-common-core-ds/src/atoms/loading-spinner/LoadingSpinner'; +import Page from '@navikt/sif-common-core-ds/src/components/page/Page'; +import SøkerInfo from './components/SøkerInfo'; +import { useInitialData } from './hooks/useInitialData'; +import '@navikt/ds-css'; +import BarnInfo from './components/BarnInfo'; +import ArbeidsgiverInfo from './components/ArbeidsgiverInfo'; + +const App = () => { + const { initialData, isLoading } = useInitialData(); + + if (isLoading || !initialData) { + return ( + +
+ +
+
+ ); + } + + const { søker, barn, arbeidsgivere } = initialData; + return ( + + + + + + + + + + + + + + + + + + + + + + + + + ); +}; + +export default App; diff --git a/apps/ungdomsytelse-soknad/src/components/ArbeidsgiverInfo.tsx b/apps/ungdomsytelse-soknad/src/components/ArbeidsgiverInfo.tsx new file mode 100644 index 000000000..d29100ecf --- /dev/null +++ b/apps/ungdomsytelse-soknad/src/components/ArbeidsgiverInfo.tsx @@ -0,0 +1,33 @@ +import { Heading, VStack } from '@navikt/ds-react'; +import { Arbeidsgivere } from '@navikt/sif-common'; +import ShadowBox from './ShadowBox'; + +interface Props { + arbeidsgivere: Arbeidsgivere; +} + +const Organisasjon = ({ organisasjon }: { organisasjon: Arbeidsgivere['organisasjoner'][0] }) => { + return ( + + + + {organisasjon.navn} + + + + ); +}; + +const ArbeidsgiverInfo = ({ arbeidsgivere: { organisasjoner } }: Props) => { + return ( + + {organisasjoner.length > 0 ? ( + organisasjoner.map((o) => ) + ) : ( + Ingen arbeidsgiver registrert + )} + + ); +}; + +export default ArbeidsgiverInfo; diff --git a/apps/ungdomsytelse-soknad/src/components/BarnInfo.tsx b/apps/ungdomsytelse-soknad/src/components/BarnInfo.tsx new file mode 100644 index 000000000..10ea48ea0 --- /dev/null +++ b/apps/ungdomsytelse-soknad/src/components/BarnInfo.tsx @@ -0,0 +1,54 @@ +import { Heading, Table, VStack } from '@navikt/ds-react'; +import { RegistrertBarn } from '@navikt/sif-common'; +import ShadowBox from './ShadowBox'; +import { dateFormatter } from '@navikt/sif-common-utils'; + +interface Props { + barn: RegistrertBarn[]; +} + +const BarnInfo = ({ barn: registrerteBarn }: Props) => { + return ( + + {registrerteBarn.map((barn, index) => ( + + + + Barn {index + 1} + + + + Felt + Verdi + + + + AktørID + {barn.aktørId} + + + Fødselsdato + {dateFormatter.compact(barn.fødselsdato)} + + + Fornavn + {barn.fornavn} + + + Mellomnavn + {barn.mellomnavn} + + + Etternavn + {barn.etternavn} + + +
+
+
+ ))} +
+ ); +}; + +export default BarnInfo; diff --git a/apps/ungdomsytelse-soknad/src/components/ShadowBox.tsx b/apps/ungdomsytelse-soknad/src/components/ShadowBox.tsx new file mode 100644 index 000000000..7793807f3 --- /dev/null +++ b/apps/ungdomsytelse-soknad/src/components/ShadowBox.tsx @@ -0,0 +1,11 @@ +import { Box } from '@navikt/ds-react'; + +const ShadowBox = ({ children }: { children: React.ReactNode }) => { + return ( + + {children} + + ); +}; + +export default ShadowBox; diff --git "a/apps/ungdomsytelse-soknad/src/components/S\303\270kerInfo.tsx" "b/apps/ungdomsytelse-soknad/src/components/S\303\270kerInfo.tsx" new file mode 100644 index 000000000..fcf028b8d --- /dev/null +++ "b/apps/ungdomsytelse-soknad/src/components/S\303\270kerInfo.tsx" @@ -0,0 +1,56 @@ +import { Heading, Table, VStack } from '@navikt/ds-react'; +import { Søker } from '@navikt/sif-common'; +import ShadowBox from './ShadowBox'; +import { dateFormatter } from '@navikt/sif-common-utils'; + +interface Props { + søker: Søker; +} + +const SøkerInfo = ({ søker }: Props) => { + return ( + + + + Søker + + + + + Felt + Verdi + + + + + AktørID + {søker.aktørId} + + + Fødselsnummer + {søker.fødselsnummer} + + + Fødselsdato + {dateFormatter.compact(søker.fødselsdato)} + + + Fornavn + {søker.fornavn} + + + Mellomnavn + {søker.mellomnavn} + + + Etternavn + {søker.etternavn} + + +
+
+
+ ); +}; + +export default SøkerInfo; diff --git a/apps/ungdomsytelse-soknad/src/hooks/useInitialData.ts b/apps/ungdomsytelse-soknad/src/hooks/useInitialData.ts new file mode 100644 index 000000000..0cd335f69 --- /dev/null +++ b/apps/ungdomsytelse-soknad/src/hooks/useInitialData.ts @@ -0,0 +1,29 @@ +import { useState } from 'react'; +import { Arbeidsgivere, fetchArbeidsgivere, fetchBarn, fetchSøker, RegistrertBarn, Søker } from '@navikt/sif-common'; +import { useEffectOnce } from '@navikt/sif-common-hooks'; +import { ISODateRangeToDateRange } from '@navikt/sif-common-utils'; + +type InitialData = { + barn: RegistrertBarn[]; + søker: Søker; + arbeidsgivere: Arbeidsgivere; +}; + +export const useInitialData = () => { + const [initialData, setInitialData] = useState(); + const [isLoading, setIsLoading] = useState(true); + + const fetchInitialData = async () => { + const søker = await fetchSøker(); + const barn = await fetchBarn(); + const arbeidsgivere = await fetchArbeidsgivere(ISODateRangeToDateRange('2020-01-01/2020-01-31')); + setInitialData({ søker, barn, arbeidsgivere }); + setIsLoading(false); + }; + + useEffectOnce(() => { + fetchInitialData(); + }); + + return { initialData, isLoading }; +}; diff --git a/apps/ungdomsytelse-soknad/src/main.tsx b/apps/ungdomsytelse-soknad/src/main.tsx new file mode 100644 index 000000000..7517b40b9 --- /dev/null +++ b/apps/ungdomsytelse-soknad/src/main.tsx @@ -0,0 +1,9 @@ +import { StrictMode } from 'react'; +import { createRoot } from 'react-dom/client'; +import App from './App'; + +createRoot(document.getElementById('root')!).render( + + + , +); diff --git a/apps/ungdomsytelse-soknad/tailwind.config.ts b/apps/ungdomsytelse-soknad/tailwind.config.ts new file mode 100644 index 000000000..6d3d9f249 --- /dev/null +++ b/apps/ungdomsytelse-soknad/tailwind.config.ts @@ -0,0 +1,7 @@ +import dsTailwind from '@navikt/ds-tailwind'; +import type { Config } from 'tailwindcss'; + +export default { + presets: [dsTailwind], + content: ['./src/**'], +} satisfies Config; diff --git a/apps/ungdomsytelse-soknad/tsconfig.json b/apps/ungdomsytelse-soknad/tsconfig.json new file mode 100644 index 000000000..23378630c --- /dev/null +++ b/apps/ungdomsytelse-soknad/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../packages/config/tsconfig-apps.json", + "compilerOptions": { + "outDir": "build/dist", + "typeRoots": ["../../node_modules/@types", "./node_modules/@types"] + }, + "exclude": ["node_modules", "src/build", "**.js", "dist"], + "include": ["./src/**/*"] +} diff --git a/apps/ungdomsytelse-soknad/vite.config.ts b/apps/ungdomsytelse-soknad/vite.config.ts new file mode 100644 index 000000000..a90906458 --- /dev/null +++ b/apps/ungdomsytelse-soknad/vite.config.ts @@ -0,0 +1,21 @@ +/* eslint-disable @typescript-eslint/no-unused-vars */ +/// +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; +import checker from 'vite-plugin-checker'; + +export default defineConfig({ + plugins: [ + react({ + include: '**/*.{tsx}', + }), + checker({ typescript: true }), + ], + server: { + port: 8080, + }, + resolve: {}, + build: { + sourcemap: true, + }, +}); diff --git a/yarn.lock b/yarn.lock index 5e3a8c078..db67f6f79 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5590,6 +5590,54 @@ __metadata: languageName: unknown linkType: soft +"@navikt/ungdomsytelse-soknad@workspace:apps/ungdomsytelse-soknad": + version: 0.0.0-use.local + resolution: "@navikt/ungdomsytelse-soknad@workspace:apps/ungdomsytelse-soknad" + dependencies: + "@eslint/eslintrc": "npm:3.1.0" + "@eslint/js": "npm:9.11.0" + "@navikt/aksel-icons": "npm:7.0.1" + "@navikt/ds-css": "npm:7.0.1" + "@navikt/ds-react": "npm:7.0.1" + "@navikt/ds-tailwind": "npm:7.0.1" + "@navikt/nav-dekoratoren-moduler": "npm:2.1.6" + "@navikt/sif-common": "npm:*" + "@navikt/sif-common-core-ds": "npm:*" + "@navikt/sif-common-soknad-ds": "npm:*" + "@navikt/sif-common-ui": "npm:*" + "@types/node": "npm:22.5.5" + "@types/react": "npm:18.3.8" + "@types/react-dom": "npm:18.3.0" + "@typescript-eslint/parser": "npm:8.6.0" + "@vitejs/plugin-react": "npm:4.3.1" + autoprefixer: "npm:10.4.20" + clsx: "npm:2.1.1" + compression: "npm:1.7.4" + date-fns: "npm:4.1.0" + eslint: "npm:9.11.0" + eslint-plugin-prettier: "npm:5.2.1" + eslint-plugin-react: "npm:7.36.1" + eslint-plugin-simple-import-sort: "npm:12.1.1" + eslint-plugin-unicorn: "npm:55.0.0" + express: "npm:4.21.0" + http-proxy-middleware: "npm:3.0.2" + mustache-express: "npm:^1.3.2" + postcss-import: "npm:16.1.0" + postcss-styled-syntax: "npm:0.6.4" + prettier: "npm:3.3.3" + react: "npm:18.3.1" + react-dom: "npm:18.3.1" + react-hook-form: "npm:7.53.0" + stylelint: "npm:16.9.0" + tailwindcss: "npm:3.4.12" + typescript: "npm:5.6.2" + typescript-eslint: "npm:8.6.0" + vite: "npm:5.4.7" + vite-plugin-checker: "npm:0.8.0" + zod: "npm:3.23.8" + languageName: unknown + linkType: soft + "@next/env@npm:14.2.13": version: 14.2.13 resolution: "@next/env@npm:14.2.13"