Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v3 - currency formatting #629

Merged
merged 2 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/app/(main)/[lang]/[slug]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,14 @@ import { fetchSeoData, generateMetadataFromSeo } from "src/utils/seo";
import { CompanyLocation } from "studio/lib/interfaces/companyDetails";
import { CompensationsPage } from "studio/lib/interfaces/compensations";
import { LegalDocument } from "studio/lib/interfaces/legalDocuments";
import { LocaleDocument } from "studio/lib/interfaces/locale";
import { BlogPage, PageBuilder, Post } from "studio/lib/interfaces/pages";
import { CustomerCasePage } from "studio/lib/interfaces/specialPages";
import {
COMPANY_LOCATIONS_QUERY,
LEGAL_DOCUMENTS_BY_SLUG_AND_LANG_QUERY,
} from "studio/lib/queries/admin";
import { LOCALE_QUERY } from "studio/lib/queries/locale";
import {
BLOG_PAGE_QUERY,
POSTS_QUERY,
Expand Down Expand Up @@ -66,6 +68,7 @@ async function Page({ params }: Props) {
initialLocationsData,
initialCustomerCases,
initialLegalDocument,
initialLocale,
] = await Promise.all([
loadStudioQuery<PageBuilder>(SLUG_QUERY, { slug }, { perspective }),
loadStudioQuery<BlogPage>(BLOG_PAGE_QUERY, { slug }, { perspective }),
Expand All @@ -89,6 +92,7 @@ async function Page({ params }: Props) {
{ slug, language: lang },
{ perspective },
),
loadStudioQuery<LocaleDocument>(LOCALE_QUERY, {}, { perspective }),
]);

if (initialPage.data) {
Expand Down Expand Up @@ -139,11 +143,13 @@ async function Page({ params }: Props) {
<CompensationsPreview
initialCompensations={initialCompensationsPage}
initialLocations={initialLocationsData}
initialLocale={initialLocale}
/>
) : (
<Compensations
compensations={initialCompensationsPage.data}
locations={initialLocationsData.data}
locale={initialLocale.data}
/>
);
}
Expand Down
21 changes: 17 additions & 4 deletions src/compensations/Compensations.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,10 @@ import {
RadioButtonGroup,
} from "src/components/forms/radioButtonGroup/RadioButtonGroup";
import Text from "src/components/text/Text";
import { formatAsCurrency } from "src/utils/i18n";
import { CompanyLocation } from "studio/lib/interfaces/companyDetails";
import { CompensationsPage } from "studio/lib/interfaces/compensations";
import { LocaleDocument } from "studio/lib/interfaces/locale";

import styles from "./compensations.module.css";
import BenefitsByLocation from "./components/benefitsByLocation/BenefitsByLocation";
Expand All @@ -26,14 +28,19 @@ import {
interface CompensationsProps {
compensations: CompensationsPage;
locations: CompanyLocation[];
locale: LocaleDocument;
}

interface SalaryCalculatorFormState {
examinationYear: number;
selectedDegree: Degree;
}

const Compensations = ({ compensations, locations }: CompensationsProps) => {
const Compensations = ({
compensations,
locations,
locale,
}: CompensationsProps) => {
const [selectedLocation, setSelectedLocation] = useState<string>(
locations[0]._id,
);
Expand Down Expand Up @@ -121,19 +128,25 @@ const Compensations = ({ compensations, locations }: CompensationsProps) => {
/>
{salary !== null ? (
<div aria-live="polite">
<Text> Du vil få en årlig lønn på {salary}</Text>
<Text>
{`Du vil få en årlig lønn på ${formatAsCurrency(salary, locale.locale, locale.currency)}`}
</Text>
{compensations.pensionPercent && (
<Text>
Du vil få en årlig pensjon på omtrent{" "}
{calculatePension(salary, compensations.pensionPercent)}
{formatAsCurrency(
calculatePension(salary, compensations.pensionPercent),
locale.locale,
locale.currency,
)}
</Text>
)}
</div>
) : null}
</>
)}
{yearlyBonusesForLocation && (
<YearlyBonuses bonuses={yearlyBonusesForLocation} />
<YearlyBonuses bonuses={yearlyBonusesForLocation} locale={locale} />
)}
<BenefitsByLocation benefits={benefitsFilteredByLocation} />
</div>
Expand Down
12 changes: 11 additions & 1 deletion src/compensations/CompensationsPreview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,23 @@ import { Suspense } from "react";

import { CompanyLocation } from "studio/lib/interfaces/companyDetails";
import { CompensationsPage } from "studio/lib/interfaces/compensations";
import { LocaleDocument } from "studio/lib/interfaces/locale";
import { COMPANY_LOCATIONS_QUERY } from "studio/lib/queries/admin";
import { LOCALE_QUERY } from "studio/lib/queries/locale";
import { COMPENSATIONS_PAGE_QUERY } from "studio/lib/queries/specialPages";

import Compensations from "./Compensations";

interface CompensationsPreviewProps {
initialCompensations: QueryResponseInitial<CompensationsPage>;
initialLocations: QueryResponseInitial<CompanyLocation[]>;
initialLocale: QueryResponseInitial<LocaleDocument>;
}

const CompensationsPreview = ({
initialCompensations,
initialLocations,
initialLocale,
}: CompensationsPreviewProps) => {
const { data: compensationsData } = useQuery<CompensationsPage>(
COMPENSATIONS_PAGE_QUERY,
Expand All @@ -30,16 +34,22 @@ const CompensationsPreview = ({
{ initial: initialLocations },
);

const { data: locale } = useQuery<LocaleDocument>(LOCALE_QUERY, {
initial: initialLocale,
});

compensationsData.salariesByLocation = stegaClean(
compensationsData.salariesByLocation,
);

return (
locationData && (
locationData &&
locale && (
<Suspense>
<Compensations
compensations={compensationsData}
locations={locationData}
locale={locale}
/>
</Suspense>
)
Expand Down
13 changes: 11 additions & 2 deletions src/compensations/components/yearlyBonuses/YearlyBonuses.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import Text from "src/components/text/Text";
import { formatAsCurrency } from "src/utils/i18n";
import { BonusPage } from "studio/lib/interfaces/compensations";
import { LocaleDocument } from "studio/lib/interfaces/locale";

import styles from "./yearlyBonuses.module.css";

interface YearlyBonusesProps {
bonuses: BonusPage[];
locale: LocaleDocument;
}

const YearlyBonuses = ({ bonuses }: YearlyBonusesProps) => {
const YearlyBonuses = ({ bonuses, locale }: YearlyBonusesProps) => {
return (
<div className={styles.wrapper}>
<Text type={"h3"}>Historisk bonus</Text>
Expand All @@ -31,7 +34,13 @@ const YearlyBonuses = ({ bonuses }: YearlyBonusesProps) => {
<Text type={"small"}>{bonus.year}</Text>
</th>
<td className={styles.bonusCell}>
<Text type={"small"}>{bonus.bonus}</Text>
<Text type={"small"}>
{formatAsCurrency(
bonus.bonus,
locale.locale,
locale.currency,
)}
</Text>
</td>
</tr>
))}
Expand Down
9 changes: 9 additions & 0 deletions src/utils/i18n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export function formatAsCurrency(
mathiazom marked this conversation as resolved.
Show resolved Hide resolved
number: number,
locale: string,
currency: string,
) {
return new Intl.NumberFormat(locale, { style: "currency", currency }).format(
number,
);
}
11 changes: 11 additions & 0 deletions studio/deskStructure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import {
CaseIcon,
CogIcon,
DoubleChevronRightIcon,
EarthGlobeIcon,
HeartIcon,
ImagesIcon,
InfoOutlineIcon,
Expand All @@ -24,6 +25,7 @@ import { languageSettingsID } from "./schemas/documents/languageSettings";
import { pageBuilderID } from "./schemas/documents/pageBuilder";
import { brandAssetsID } from "./schemas/documents/siteSettings/brandAssets";
import { brokenLinkID } from "./schemas/documents/siteSettings/brokenLink";
import { localeID } from "./schemas/documents/siteSettings/locale";
import { soMeLinksID } from "./schemas/documents/siteSettings/socialMediaProfiles";
import { customerCasesPageID } from "./schemas/documents/specialPages/customerCasesPage";

Expand Down Expand Up @@ -102,6 +104,15 @@ const siteSettingSection = (S: StructureBuilder) =>
.documentId(languageSettingsID)
.title("Languages"),
),
S.listItem()
.title("Region")
.icon(EarthGlobeIcon)
.child(
S.document()
.schemaType(localeID)
.documentId(localeID)
.title("Region"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Region --> Locale / currency

),
S.listItem()
.title("Default SEO")
.icon(SearchIcon)
Expand Down
4 changes: 4 additions & 0 deletions studio/lib/interfaces/locale.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface LocaleDocument {
locale: string;
currency: string;
}
5 changes: 5 additions & 0 deletions studio/lib/queries/locale.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { groq } from "next-sanity";

import { localeID } from "studio/schemas/documents/siteSettings/locale";

export const LOCALE_QUERY = groq`*[_type == "${localeID}" && _id == "${localeID}"][0]`;
2 changes: 2 additions & 0 deletions studio/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import pageBuilder from "./schemas/documents/pageBuilder";
import posts from "./schemas/documents/post";
import brandAssets from "./schemas/documents/siteSettings/brandAssets";
import brokenLink from "./schemas/documents/siteSettings/brokenLink";
import locale from "./schemas/documents/siteSettings/locale";
import navigationManager from "./schemas/documents/siteSettings/navigationManager";
import socialMediaLinks from "./schemas/documents/siteSettings/socialMediaProfiles";
import customerCasesPage from "./schemas/documents/specialPages/customerCasesPage";
Expand Down Expand Up @@ -43,5 +44,6 @@ export const schema: { types: SchemaTypeDefinition[] } = {
defaultSeo,
brandAssets,
languageSettings,
locale,
],
};
41 changes: 41 additions & 0 deletions studio/schemas/documents/siteSettings/locale.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { defineField, defineType } from "sanity";

import { relevantCurrencies } from "studio/utils/currencies";
import { relevantLocales } from "studio/utils/locales";

export const localeID = "locale";

const locale = defineType({
name: localeID,
type: "document",
fields: [
defineField({
name: "locale",
type: "string",
title: "Region",
anemne marked this conversation as resolved.
Show resolved Hide resolved
description: "Select the most relevant region for the website.",
initialValue: relevantLocales[0].code,
options: {
list: relevantLocales.map(({ title, code }) => ({
title: `${title} (${code})`,
value: code,
})),
},
}),
defineField({
name: "currency",
type: "string",
title: "Currency",
description: "Select the most relevant currency for the website.",
initialValue: relevantCurrencies[0].code,
options: {
list: relevantCurrencies.map(({ title, code }) => ({
title: `${title} (${code})`,
value: code,
})),
},
}),
],
});

export default locale;
36 changes: 36 additions & 0 deletions studio/utils/currencies.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
interface Currency {
title: string;
code: string;
}

// ISO 4217 currency codes (https://en.wikipedia.org/wiki/ISO_4217#List_of_ISO_4217_currency_codes)
export const relevantCurrencies: Currency[] = [
{
title: "🇳🇴 Norwegian Krone",
code: "NOK",
},
{
title: "🇸🇪 Swedish Krona",
code: "SEK",
},
{
title: "🇪🇺 Euro",
code: "EUR",
},
{
title: "🇬🇧 British Pound",
code: "GBP",
},
{
title: "🇺🇸 US Dollar",
code: "USD",
},
{
title: "🇩🇰 Danish Krone",
code: "DKK",
},
{
title: "🇮🇸 Icelandic Króna",
mathiazom marked this conversation as resolved.
Show resolved Hide resolved
code: "ISK",
},
];
39 changes: 39 additions & 0 deletions studio/utils/locales.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
interface Locale {
title: string;
code: string;
}

export const relevantLocales: Locale[] = [
{
title: "🇳🇴 Norway",
code: "nb-NO",
},
// {
// title: "🇳🇴 Norway",
// code: "nn-NO",
mathiazom marked this conversation as resolved.
Show resolved Hide resolved
// },
{
title: "🇸🇪 Sweden",
code: "sv-SE",
},
{
title: "🇬🇧 United Kingdom",
code: "en-GB",
},
{
title: "🇺🇸 United States",
code: "en-US",
},
{
title: "🇩🇰 Denmark",
code: "da-DK",
},
{
title: "🇫🇮 Finland",
code: "fi-FI",
},
{
title: "🇮🇸 Iceland",
code: "is-IS",
},
];