diff --git a/apps/services/auth/ids-api/src/openapi.yaml b/apps/services/auth/ids-api/src/openapi.yaml index 0a8601fd..46709742 100644 --- a/apps/services/auth/ids-api/src/openapi.yaml +++ b/apps/services/auth/ids-api/src/openapi.yaml @@ -2360,7 +2360,7 @@ components: expiration: format: date-time type: string - example: 2025-05-08T09:53:30.554Z + example: 2025-05-09T07:13:23.068Z consumedTime: format: date-time type: string @@ -2413,7 +2413,7 @@ components: expiration: format: date-time type: string - example: 2025-05-08T09:53:30.612Z + example: 2025-05-09T07:13:23.125Z consumedTime: type: object data: diff --git a/apps/services/auth/personal-representative-public/src/openapi.yaml b/apps/services/auth/personal-representative-public/src/openapi.yaml index 7c3cd31b..bacb62c8 100644 --- a/apps/services/auth/personal-representative-public/src/openapi.yaml +++ b/apps/services/auth/personal-representative-public/src/openapi.yaml @@ -343,11 +343,11 @@ components: validFrom: format: date-time type: string - example: 2025-05-06T09:53:25.263Z + example: 2025-05-07T07:13:17.918Z validTo: format: date-time type: string - example: 2025-05-08T09:53:25.263Z + example: 2025-05-09T07:13:17.918Z required: - code - description diff --git a/apps/services/auth/personal-representative/src/openapi.yaml b/apps/services/auth/personal-representative/src/openapi.yaml index 7825b91e..3e068eb9 100644 --- a/apps/services/auth/personal-representative/src/openapi.yaml +++ b/apps/services/auth/personal-representative/src/openapi.yaml @@ -1032,11 +1032,11 @@ components: validFrom: format: date-time type: string - example: 2025-05-06T09:53:29.098Z + example: 2025-05-07T07:13:21.877Z validTo: format: date-time type: string - example: 2025-05-08T09:53:29.098Z + example: 2025-05-09T07:13:21.877Z required: - code - description @@ -1135,7 +1135,7 @@ components: validTo: format: date-time type: string - example: 2025-05-08T09:53:29.087Z + example: 2025-05-09T07:13:21.867Z rights: example: >- [{code:"health", description:"health descr", validFrom:"xx.yy.zzzz", @@ -1222,7 +1222,7 @@ components: validTo: format: date-time type: string - example: 2025-05-08T09:53:29.090Z + example: 2025-05-09T07:13:21.869Z rightCodes: example: '["health", "finance"]' description: >- @@ -1254,7 +1254,7 @@ components: validTo: format: date-time type: string - example: 2025-05-08T09:53:29.096Z + example: 2025-05-09T07:13:21.874Z required: - code - name diff --git a/apps/services/endorsements/api/src/openapi.yaml b/apps/services/endorsements/api/src/openapi.yaml index 147fdace..20888e00 100644 --- a/apps/services/endorsements/api/src/openapi.yaml +++ b/apps/services/endorsements/api/src/openapi.yaml @@ -1054,11 +1054,11 @@ components: openedDate: format: date-time type: string - default: 2025-05-07T09:51:13.496Z + default: 2025-05-08T07:11:05.497Z closedDate: format: date-time type: string - default: 2025-06-07T09:51:13.496Z + default: 2025-06-08T07:11:05.497Z adminLock: type: boolean default: false diff --git a/apps/services/user-notification/src/openapi.yaml b/apps/services/user-notification/src/openapi.yaml index b9abb16e..3a6d0981 100644 --- a/apps/services/user-notification/src/openapi.yaml +++ b/apps/services/user-notification/src/openapi.yaml @@ -806,11 +806,11 @@ components: created: format: date-time type: string - example: '2025-05-07T09:51:06.931Z' + example: '2025-05-08T07:10:59.050Z' updated: format: date-time type: string - example: '2025-05-07T09:51:06.931Z' + example: '2025-05-08T07:10:59.050Z' read: type: boolean example: false diff --git a/apps/tax/constants/index.ts b/apps/tax/constants/index.ts index 42302e6c..250ed2a8 100644 --- a/apps/tax/constants/index.ts +++ b/apps/tax/constants/index.ts @@ -17,3 +17,4 @@ export const PRELOADED_FONTS = [ '/fonts/ibm-plex-sans-v7-latin-500.woff2', '/fonts/ibm-plex-sans-v7-latin-600.woff2', ] +export const REQUIRED_ERROR_MESSAGE = 'nauðsynlegur reitur' diff --git a/apps/tax/pages/login/index.tsx b/apps/tax/pages/login/index.tsx index da139fb4..6339f330 100644 --- a/apps/tax/pages/login/index.tsx +++ b/apps/tax/pages/login/index.tsx @@ -1,24 +1,38 @@ -import React from 'react' +import React, {useState} from 'react' import router from 'next/router' +import { + useLazyQuery, +} from "@apollo/client"; import { AlertMessage, Box, Button, Checkbox, Input, Link, Logo, Text } from '@island.is/island-ui/core' import { formWrapper } from '@island.is/tax/screens/Tax/login/Login.css' -export async function getServerSideProps() { - const taxData = { - country: 'test', - vatRate: 10, - description: 'test', - } +import {GetUserByPhoneQuery} from '../../graphql/schema' +import { withApollo } from "../../graphql/withApollo"; +import { + GET_USER_BY_PHONE_QUERY, +} from "../../screens/queries"; + +const Login = () => { + const [phone, setPhone] = useState(''); + const [isError, setIsError] = useState(false); + + const [fetchUser] = useLazyQuery(GET_USER_BY_PHONE_QUERY); - return { - props: { - taxInfo: taxData, - }, + const onLogin = async () => { + const result = await fetchUser({ + variables: { + phone, + }, + }); + if (result.data) { + localStorage.setItem('session_token', result.data.userByPhone.id); + void router.push('tax'); + } else { + setIsError(true); + } } -} -const Login = ({ loginInfo }) => { return ( { á mínar síður Ísland.is - - - + { + isError && ( + + + + ) + } { name="" size="sm" placeholder="000-0000" - type="number" + type="tel" + value={phone} + onChange={(e) => setPhone(e.target.value)} /> @@ -78,7 +98,7 @@ const Login = ({ loginInfo }) => { colorScheme="default" fluid variant="primary" - onClick={() => router.push('tax')} + onClick={onLogin} > Auðkenna @@ -133,4 +153,4 @@ const Login = ({ loginInfo }) => { ) } -export default Login +export default withApollo(Login); diff --git a/apps/tax/pages/tax/index.tsx b/apps/tax/pages/tax/index.tsx index 70fdd8c1..513d3f27 100644 --- a/apps/tax/pages/tax/index.tsx +++ b/apps/tax/pages/tax/index.tsx @@ -2,13 +2,7 @@ import React, { useState } from 'react' import { Box, FormStepperV2, Section } from '@island.is/island-ui/core' import FormStepsLayout from '@island.is/tax/screens/Layouts/FormStepsLayout' -import StepFive from '@island.is/tax/screens/Tax/steps/StepFive' -import StepFour from '@island.is/tax/screens/Tax/steps/StepFour' -import StepOne from '@island.is/tax/screens/Tax/steps/StepOne' -import StepSeven from '@island.is/tax/screens/Tax/steps/StepSeven' -import StepSix from '@island.is/tax/screens/Tax/steps/StepSix' -import StepThree from '@island.is/tax/screens/Tax/steps/StepThree' -import StepTwo from '@island.is/tax/screens/Tax/steps/StepTwo' +import { StepFive, StepFour, StepOne, StepSeven, StepSix, StepThree, StepTwo } from '@island.is/tax/screens/Tax/steps' const steps = [ { title: 'Gagnaöflun', index: 0 }, diff --git a/apps/tax/screens/Tax/Buttons.tsx b/apps/tax/screens/Tax/Buttons.tsx index 6741645e..34cf5ff1 100644 --- a/apps/tax/screens/Tax/Buttons.tsx +++ b/apps/tax/screens/Tax/Buttons.tsx @@ -2,12 +2,13 @@ import { Box, Button } from '@island.is/island-ui/core' type ButtonProps = { onForward: () => void - onBackward: () => void + onBackward: () => void, + isLastStep?: boolean, } -const Buttons = ({ onForward, onBackward }: ButtonProps) => { +const Buttons = ({ onForward, onBackward, isLastStep }: ButtonProps) => { return ( - + ) diff --git a/apps/tax/screens/Tax/steps/StepFive.tsx b/apps/tax/screens/Tax/steps/StepFive.tsx index b46d1c06..9244cf1e 100644 --- a/apps/tax/screens/Tax/steps/StepFive.tsx +++ b/apps/tax/screens/Tax/steps/StepFive.tsx @@ -1,12 +1,16 @@ +import { useForm } from 'react-hook-form' + import { AlertMessage, Box, + DatePicker, GridColumn, GridContainer, GridRow, - Input, Text, } from '@island.is/island-ui/core' +import { InputController } from '@island.is/shared/form-fields' +import { REQUIRED_ERROR_MESSAGE } from '@island.is/tax/constants' import Buttons from '../Buttons' @@ -15,7 +19,25 @@ type StepFiveProps = { onBackward: () => void } +interface InputState { + residentialLocation: string + loanNumber: string + borrowingDate: Date + loanTerm: number + lenderId: string + lenderName: string + totalPaymentsYear: number + nominalValue: number + interest: number + debt: number +} + const StepFive = ({ onForward, onBackward }: StepFiveProps) => { + const { control, handleSubmit, formState } = useForm() + + const onSubmit = (inputState: InputState) => { + onForward() + } return ( { - { - { - - { - { - { - { - { - { - { - + ) } diff --git a/apps/tax/screens/Tax/steps/StepFour.tsx b/apps/tax/screens/Tax/steps/StepFour.tsx index 8b1292b3..02a9d9c3 100644 --- a/apps/tax/screens/Tax/steps/StepFour.tsx +++ b/apps/tax/screens/Tax/steps/StepFour.tsx @@ -1,13 +1,23 @@ +import { useEffect, useMemo } from 'react' +import { useForm } from 'react-hook-form' +import { useMutation,useQuery } from '@apollo/client' + import { Box, Button, + Divider, GridColumn, GridContainer, GridRow, Input, Text, } from '@island.is/island-ui/core' +import { InputController } from '@island.is/shared/form-fields' +import { REQUIRED_ERROR_MESSAGE } from '@island.is/tax/constants' +import {GetUserQuery} from '../../../graphql/schema' +import { withApollo } from "../../../graphql/withApollo"; +import { CREATE_ASSET_MUTATION, GET_USER_QUERY, UPDATE_ASSET_MUTATION } from '../../queries' import Buttons from '../Buttons' type StepFourProps = { @@ -15,7 +25,51 @@ type StepFourProps = { onBackward: () => void } +interface InputState { + assetNumber: string + propertyLocation: string + propertyValue: string +} + +const formatter = new Intl.NumberFormat('is-IS', { + style: 'decimal', + minimumFractionDigits: 0, + maximumFractionDigits: 0 +}); + const StepFour = ({ onForward, onBackward }: StepFourProps) => { + const { control, handleSubmit, formState, setValue, watch } = useForm(); + const [createAsset] = useMutation(CREATE_ASSET_MUTATION); + const [updateAsset] = useMutation(UPDATE_ASSET_MUTATION); + const { data } = useQuery(GET_USER_QUERY, { + variables: { + // Getting user id from local storage demo purpose + id: Number(localStorage.getItem('session_token')), + }, + }); + + const assetData = useMemo(() => data?.user.taxReturns?.[0]?.assets?.[0], [data?.user.taxReturns]); + + useEffect(() => { + if (assetData) { + setValue('assetNumber', assetData.assetId ?? '') + setValue('propertyLocation', assetData.address ?? '') + setValue('propertyValue', assetData.value? assetData.value.toString() : '') + } + }, [assetData, setValue]); + + const propertyValue = watch('propertyValue'); + + const onSubmit = async (inputState: InputState) => { + if (assetData) { + await updateAsset({ variables: { asset: {id: Number(assetData.id), assetId: inputState.assetNumber, address: inputState.propertyLocation, value: Number(inputState.propertyValue) }}}); + onForward(); + } else { + await createAsset({ variables: { asset: {taxReturnId: data?.user.taxReturns?.[0].id, assetId: inputState.assetNumber, address: inputState.propertyLocation, value: Number(inputState.propertyValue) }}}); + onForward(); + } + } + return ( { - - - - + + + + + + + + + + + ) } -export default StepFour +export default withApollo(StepFour) diff --git a/apps/tax/screens/Tax/steps/StepOne.tsx b/apps/tax/screens/Tax/steps/StepOne.tsx index 1fe21eb9..5275b4c1 100644 --- a/apps/tax/screens/Tax/steps/StepOne.tsx +++ b/apps/tax/screens/Tax/steps/StepOne.tsx @@ -46,7 +46,7 @@ const StepOne = ({ onForward, onBackward }: StepOneProps) => { verður sótt til Skattsins. - + { Þú getur nálgast álagningarseðil á mínum síðum - + Þú getur einnig sótt stafrænt afrit af framtali, fylgiskjölum og álagningarseðli á mínum síðum. Þar má finna rafrænt afrit af skattaframtölum fyrir gjaldárin 2006 og síðar. Ef þú skilaðir ekki framtali er einungis álagningarseðill birtur. - + + + ) } diff --git a/apps/tax/screens/Tax/steps/StepSix.tsx b/apps/tax/screens/Tax/steps/StepSix.tsx index 41a081e6..f52c4156 100644 --- a/apps/tax/screens/Tax/steps/StepSix.tsx +++ b/apps/tax/screens/Tax/steps/StepSix.tsx @@ -540,13 +540,13 @@ const StepSix = ({ onForward, onBackward }: StepSixProps) => { - + - + ) } diff --git a/apps/tax/screens/Tax/steps/StepThree.tsx b/apps/tax/screens/Tax/steps/StepThree.tsx index 320c863b..6b706c11 100644 --- a/apps/tax/screens/Tax/steps/StepThree.tsx +++ b/apps/tax/screens/Tax/steps/StepThree.tsx @@ -1,3 +1,7 @@ +import { useEffect, useMemo } from 'react' +import { useForm } from 'react-hook-form' +import { useMutation,useQuery } from '@apollo/client' + import { Box, Button, @@ -8,7 +12,12 @@ import { Input, Text, } from '@island.is/island-ui/core' +import { InputController } from '@island.is/shared/form-fields' +import { REQUIRED_ERROR_MESSAGE } from '@island.is/tax/constants' +import {GetUserQuery} from '../../../graphql/schema' +import { withApollo } from "../../../graphql/withApollo"; +import { CREATE_INCOME_MUTATION, GET_USER_QUERY, UPDATE_INCOME_MUTATION } from '../../queries' import Buttons from '../Buttons' type StepThreeProps = { @@ -16,7 +25,49 @@ type StepThreeProps = { onBackward: () => void } +interface InputState { + employerName: string + salary: number +} + +const formatter = new Intl.NumberFormat('is-IS', { + style: 'decimal', + minimumFractionDigits: 0, + maximumFractionDigits: 0 +}); + const StepThree = ({ onForward, onBackward }: StepThreeProps) => { + const { control, handleSubmit, formState, setValue, watch } = useForm(); + const [createIncome] = useMutation(CREATE_INCOME_MUTATION); + const [updateIncome] = useMutation(UPDATE_INCOME_MUTATION); + const { data } = useQuery(GET_USER_QUERY, { + variables: { + // Getting user id from local storage demo purpose + id: Number(localStorage.getItem('session_token')), + }, + }); + + const incomeData = useMemo(() => data?.user.taxReturns?.[0]?.incomes?.[0], [data?.user.taxReturns]); + + useEffect(() => { + if (incomeData) { + setValue('employerName', incomeData.source) + setValue('salary', incomeData.amount) + } + }, [incomeData, data?.user.taxReturns, setValue]); + + const salary = watch('salary'); + + const onSubmit = async (inputState: InputState) => { + if (incomeData) { + await updateIncome({ variables: { income: {id: Number(incomeData.id), source: inputState.employerName, amount: Number(inputState.salary), type: 'salary' }}}); + onForward(); + } else { + await createIncome({ variables: { income: {taxReturnId: data?.user.taxReturns?.[0].id, source: inputState.employerName, amount: Number(inputState.salary), type: 'salary' }}}); + onForward(); + } + } + return ( { Launatekjur og starfstengdar greiðslur - - Nafn launagreiðanda - + Nafn launagreiðanda + + - Laun + + Laun + - - - - + @@ -114,17 +158,17 @@ const StepThree = ({ onForward, onBackward }: StepThreeProps) => { backgroundColor="white" maxLength={4} name="Input" - placeholder="10.260.000 kr." + value={formatter.format(salary ?? 0) + ' kr.'} rows={0} size="xs" - type="number" + type="text" /> - + ) } -export default StepThree +export default withApollo(StepThree) diff --git a/apps/tax/screens/Tax/steps/StepTwo.tsx b/apps/tax/screens/Tax/steps/StepTwo.tsx index c8f0b354..eac2b084 100644 --- a/apps/tax/screens/Tax/steps/StepTwo.tsx +++ b/apps/tax/screens/Tax/steps/StepTwo.tsx @@ -1,3 +1,5 @@ +import { useQuery, useMutation } from '@apollo/client' + import { AlertMessage, Box, @@ -9,6 +11,9 @@ import { } from '@island.is/island-ui/core' import { fieldWrapper } from '@island.is/tax/screens/Tax/steps/StepTwo.css' +import {GetUserQuery} from '../../../graphql/schema' +import { withApollo } from "../../../graphql/withApollo"; +import { CREATE_TAX_RETURN_MUTATION, GET_USER_QUERY } from '../../queries' import Buttons from '../Buttons' type StepTwoProps = { @@ -17,6 +22,21 @@ type StepTwoProps = { } const StepTwo = ({ onForward, onBackward }: StepTwoProps) => { + const [createTaxReturn] = useMutation(CREATE_TAX_RETURN_MUTATION); + const { data } = useQuery(GET_USER_QUERY, { + variables: { + // Getting user id from local storage demo purpose + id: Number(localStorage.getItem('session_token')), + }, + }); + + const onNext = async () => { + if (!data?.user.taxReturns || data.user.taxReturns.length === 0) { + await createTaxReturn({ variables: { taxReturn: {userId: Number(data?.user.id), year: 2025, status: 'draft' }}}); + } + onForward(); + } + return ( { backgroundColor="white" label="Fullt nafn" name="" - value="Jökull Þórðarson" + value={data?.user.firstName + ' ' + data?.user.lastName} size="sm" type="text" /> @@ -48,11 +68,11 @@ const StepTwo = ({ onForward, onBackward }: StepTwoProps) => { @@ -62,7 +82,7 @@ const StepTwo = ({ onForward, onBackward }: StepTwoProps) => { backgroundColor="white" label="Heimili" name="" - value="Bláfjallagata 12" + value={data?.user.streetAndHouseNumber ?? ""} size="sm" type="text" /> @@ -75,7 +95,7 @@ const StepTwo = ({ onForward, onBackward }: StepTwoProps) => { backgroundColor="white" label="Póstnúmer" name="" - value="105" + value={data?.user.postalCode ?? 0} size="sm" type="number" /> @@ -87,7 +107,7 @@ const StepTwo = ({ onForward, onBackward }: StepTwoProps) => { backgroundColor="white" label="Sveitarfélag" name="" - value="Reykjavík" + value={data?.user.city ?? ""} size="sm" type="text" /> @@ -100,9 +120,10 @@ const StepTwo = ({ onForward, onBackward }: StepTwoProps) => { backgroundColor="white" label="Netfang " name="" - value="jokull.thordarson@email.is" + value={data?.user.email ?? ""} size="sm" type="email" + autoComplete="off" /> @@ -112,7 +133,7 @@ const StepTwo = ({ onForward, onBackward }: StepTwoProps) => { backgroundColor="white" label="Símanúmer" name="" - value="+354 772-8391" + value={data?.user.phone ?? ""} size="sm" type="tel" /> @@ -126,9 +147,9 @@ const StepTwo = ({ onForward, onBackward }: StepTwoProps) => { message="Ef netfang og símanúmer er ekki rétt hér að ofan þá verður að breyta þeim upplýsingum á mínum síðum Ísland.is" /> - + ) } -export default StepTwo +export default withApollo(StepTwo); diff --git a/apps/tax/screens/Tax/steps/index.ts b/apps/tax/screens/Tax/steps/index.ts new file mode 100644 index 00000000..01f0471d --- /dev/null +++ b/apps/tax/screens/Tax/steps/index.ts @@ -0,0 +1,9 @@ +import StepOne from "./StepOne"; +import StepTwo from "./StepTwo"; +import StepThree from "./StepThree"; +import StepFour from "./StepFour"; +import StepFive from "./StepFive"; +import StepSix from "./StepSix"; +import StepSeven from "./StepSeven"; + +export {StepOne, StepTwo, StepThree, StepFour, StepFive, StepSix, StepSeven} \ No newline at end of file