@treely/strapi-slices 5.15.0 → 5.16.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/components/CreditsAvailableBadge/CreditsAvailableBadge.d.ts +2 -2
- package/dist/models/PortfolioProject.d.ts +0 -2
- package/dist/models/fpm/FPMProject.d.ts +7 -0
- package/dist/models/strapi/StrapiProject.d.ts +0 -2
- package/dist/rootMessages.de.d.ts +0 -4
- package/dist/rootMessages.en.d.ts +0 -4
- package/dist/slices/ProjectGridCard/ProjectGridCard.d.ts +6 -0
- package/dist/slices/ProjectGridCard/index.d.ts +2 -0
- package/dist/slices/ProjectsGrid/ProjectsGrid.d.ts +3 -1
- package/dist/slices/ProjectsMap/MapMarker.d.ts +3 -3
- package/dist/strapi-slices.cjs.development.js +172 -161
- package/dist/strapi-slices.cjs.development.js.map +1 -1
- package/dist/strapi-slices.cjs.production.min.js +1 -1
- package/dist/strapi-slices.cjs.production.min.js.map +1 -1
- package/dist/strapi-slices.esm.js +175 -164
- package/dist/strapi-slices.esm.js.map +1 -1
- package/dist/test/integrationMocks/fpmPortoflioProjectMock.d.ts +3 -0
- package/dist/utils/getMessages.d.ts +0 -8
- package/package.json +1 -1
- package/src/components/CreditsAvailableBadge/CreditsAvailableBadge.test.tsx +8 -6
- package/src/components/CreditsAvailableBadge/CreditsAvailableBadge.tsx +34 -22
- package/src/components/CreditsAvailableBadge/messages.de.ts +1 -1
- package/src/components/portfolio/ProjectInfo/ProjectInfo.tsx +3 -7
- package/src/integrations/fpmClient.ts +7 -1
- package/src/integrations/strapi/getPortfolioProjects.test.ts +2 -2
- package/src/integrations/strapi/getPortfolioProjects.ts +4 -7
- package/src/integrations/strapi/getStaticPropsFromStrapi.ts +2 -1
- package/src/integrations/strapi/getStrapiCollectionType.ts +2 -1
- package/src/integrations/strapi/getStrapiSingleType.ts +3 -1
- package/src/integrations/strapi/strapiClient.ts +7 -1
- package/src/models/PortfolioProject.ts +0 -2
- package/src/models/fpm/FPMProject.ts +8 -0
- package/src/models/strapi/StrapiProject.ts +0 -2
- package/src/rootMessages.de.ts +0 -2
- package/src/rootMessages.en.ts +0 -2
- package/src/slices/ProjectFacts/ProjectFacts.stories.tsx +1 -2
- package/src/slices/ProjectGridCard/ProjectGridCard.test.tsx +54 -0
- package/src/slices/ProjectGridCard/ProjectGridCard.tsx +57 -0
- package/src/slices/ProjectGridCard/index.ts +3 -0
- package/src/slices/ProjectsGrid/ProjectsGrid.stories.tsx +1 -1
- package/src/slices/ProjectsGrid/ProjectsGrid.test.tsx +0 -2
- package/src/slices/ProjectsGrid/ProjectsGrid.tsx +5 -3
- package/src/slices/ProjectsMap/MapMarker.test.tsx +3 -2
- package/src/slices/ProjectsMap/MapMarker.tsx +9 -12
- package/src/slices/ProjectsMap/ProjectsMap.stories.tsx +0 -2
- package/src/slices/ProjectsMap/ProjectsMap.tsx +1 -1
- package/src/slices/TextWithCard/TextWithCard.stories.tsx +2 -3
- package/src/slices/TextWithCard/TextWithCard.tsx +2 -2
- package/src/test/integrationMocks/fpmPortoflioProjectMock.ts +16 -0
- package/src/test/integrationMocks/fpmProjectMock.ts +2 -1
- package/src/test/integrationMocks/portfolioProjectMock.ts +1 -3
- package/src/test/mocks/portfolioProjectMock.ts +0 -2
- package/src/test/strapiMocks/strapiProject.ts +0 -2
- package/dist/components/portfolio/PortfolioProjectCard/PortfolioProjectCard.d.ts +0 -6
- package/dist/components/portfolio/PortfolioProjectCard/index.d.ts +0 -2
- package/dist/components/portfolio/PortfolioProjectCard/messages.de.d.ts +0 -7
- package/dist/components/portfolio/PortfolioProjectCard/messages.en.d.ts +0 -7
- package/dist/models/CreditsAvailableState.d.ts +0 -7
- package/src/components/portfolio/PortfolioProjectCard/PortfolioProjectCard.test.tsx +0 -53
- package/src/components/portfolio/PortfolioProjectCard/PortfolioProjectCard.tsx +0 -69
- package/src/components/portfolio/PortfolioProjectCard/index.ts +0 -3
- package/src/components/portfolio/PortfolioProjectCard/messages.de.ts +0 -8
- package/src/components/portfolio/PortfolioProjectCard/messages.en.ts +0 -8
- package/src/models/CreditsAvailableState.ts +0 -8
|
@@ -59,10 +59,6 @@ declare const getMessages: (locale: string) => {
|
|
|
59
59
|
'features.projectInfo.properties.forecastedAmountYear.toolTip': string;
|
|
60
60
|
'features.projectInfo.properties.riskBuffer': string;
|
|
61
61
|
'features.projectInfo.properties.year': string;
|
|
62
|
-
'components.portfolioProjectCard.text.yes': string;
|
|
63
|
-
'components.portfolioProjectCard.text.some': string;
|
|
64
|
-
'components.portfolioProjectCard.text.no': string;
|
|
65
|
-
'components.portfolioProjectCard.text.notYet': string;
|
|
66
62
|
'features.portfolio.documentsDownloadList.projectDocuments': string;
|
|
67
63
|
'features.portfolio.documentsDownloadList.downloadDocument': string;
|
|
68
64
|
'components.creditsAvailableBadge.text.yes': string;
|
|
@@ -130,10 +126,6 @@ declare const getMessages: (locale: string) => {
|
|
|
130
126
|
'features.projectInfo.properties.forecastedAmountYear.label': string;
|
|
131
127
|
'features.projectInfo.properties.riskBuffer': string;
|
|
132
128
|
'features.projectInfo.properties.year': string;
|
|
133
|
-
'components.portfolioProjectCard.text.yes': string;
|
|
134
|
-
'components.portfolioProjectCard.text.some': string;
|
|
135
|
-
'components.portfolioProjectCard.text.no': string;
|
|
136
|
-
'components.portfolioProjectCard.text.notYet': string;
|
|
137
129
|
'features.portfolio.documentsDownloadList.projectDocuments': string;
|
|
138
130
|
'features.portfolio.documentsDownloadList.downloadDocument': string;
|
|
139
131
|
'components.creditsAvailableBadge.text.yes': string;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render, screen } from '../../test/testUtils';
|
|
3
|
-
import CreditsAvailableState from '../../models/CreditsAvailableState';
|
|
4
3
|
import CreditsAvailableBadge, {
|
|
5
4
|
CreditsAvailableBadgeProps,
|
|
6
5
|
} from './CreditsAvailableBadge';
|
|
7
6
|
import messagesEn from './messages.en';
|
|
7
|
+
import { CreditAvailability } from '../../models/fpm/FPMProject';
|
|
8
8
|
|
|
9
9
|
const defaultProps: CreditsAvailableBadgeProps = {
|
|
10
|
-
status:
|
|
10
|
+
status: CreditAvailability.CREDITS_AVAILABLE,
|
|
11
11
|
};
|
|
12
12
|
|
|
13
13
|
const setup = (props: Partial<CreditsAvailableBadgeProps> = {}) => {
|
|
@@ -34,12 +34,14 @@ describe('The CreditsAvailableBadge component', () => {
|
|
|
34
34
|
screen.getByText(messagesEn['components.creditsAvailableBadge.text.yes'])
|
|
35
35
|
).toBeInTheDocument();
|
|
36
36
|
expect(
|
|
37
|
-
screen
|
|
37
|
+
screen
|
|
38
|
+
.getByText(messagesEn['components.creditsAvailableBadge.text.yes'])
|
|
39
|
+
.closest('a')
|
|
38
40
|
).toHaveAttribute('href', 'link-to');
|
|
39
41
|
});
|
|
40
42
|
|
|
41
43
|
it('renders correctly for the "some" case', () => {
|
|
42
|
-
setup({ status:
|
|
44
|
+
setup({ status: CreditAvailability.SOME_CREDITS_AVAILABLE });
|
|
43
45
|
|
|
44
46
|
expect(
|
|
45
47
|
screen.getByText(messagesEn['components.creditsAvailableBadge.text.some'])
|
|
@@ -47,7 +49,7 @@ describe('The CreditsAvailableBadge component', () => {
|
|
|
47
49
|
});
|
|
48
50
|
|
|
49
51
|
it('renders correctly for the "no" case', () => {
|
|
50
|
-
setup({ status:
|
|
52
|
+
setup({ status: CreditAvailability.NO_CREDITS_AVAILABLE });
|
|
51
53
|
|
|
52
54
|
expect(
|
|
53
55
|
screen.getByText(messagesEn['components.creditsAvailableBadge.text.no'])
|
|
@@ -55,7 +57,7 @@ describe('The CreditsAvailableBadge component', () => {
|
|
|
55
57
|
});
|
|
56
58
|
|
|
57
59
|
it('renders correctly for the "notYet" case', () => {
|
|
58
|
-
setup({ status:
|
|
60
|
+
setup({ status: CreditAvailability.SOON_CREDITS_AVAILABLE });
|
|
59
61
|
|
|
60
62
|
expect(
|
|
61
63
|
screen.getByText(
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import React, { useContext } from 'react';
|
|
2
|
-
import
|
|
3
|
-
import { Badge } from 'boemly';
|
|
2
|
+
import { Flex, Spacer, Tag, Text } from 'boemly';
|
|
4
3
|
import NextLink from 'next/link';
|
|
5
4
|
import { IntlContext } from '../ContextProvider';
|
|
5
|
+
import { CreditAvailability } from '../../models/fpm/FPMProject';
|
|
6
|
+
import { Info } from '@phosphor-icons/react';
|
|
6
7
|
|
|
7
8
|
export interface CreditsAvailableBadgeProps {
|
|
8
|
-
status:
|
|
9
|
+
status: CreditAvailability;
|
|
9
10
|
href?: string;
|
|
10
11
|
}
|
|
11
12
|
|
|
@@ -16,40 +17,51 @@ const CreditsAvailableBadge = ({
|
|
|
16
17
|
const { formatMessage } = useContext(IntlContext);
|
|
17
18
|
|
|
18
19
|
const variants: Record<
|
|
19
|
-
|
|
20
|
-
{
|
|
20
|
+
CreditAvailability,
|
|
21
|
+
{ message: string; color: string }
|
|
21
22
|
> = {
|
|
22
|
-
[
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
[CreditAvailability.CREDITS_AVAILABLE]: {
|
|
24
|
+
message: formatMessage({
|
|
25
|
+
id: 'components.creditsAvailableBadge.text.yes',
|
|
26
|
+
}),
|
|
27
|
+
color: 'var(--boemly-colors-primary-800)',
|
|
25
28
|
},
|
|
26
|
-
[
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
[CreditAvailability.NO_CREDITS_AVAILABLE]: {
|
|
30
|
+
message: formatMessage({
|
|
31
|
+
id: 'components.creditsAvailableBadge.text.no',
|
|
32
|
+
}),
|
|
33
|
+
color: 'var(--boemly-colors-red-600)',
|
|
29
34
|
},
|
|
30
|
-
[
|
|
31
|
-
|
|
32
|
-
|
|
35
|
+
[CreditAvailability.SOME_CREDITS_AVAILABLE]: {
|
|
36
|
+
message: formatMessage({
|
|
37
|
+
id: 'components.creditsAvailableBadge.text.some',
|
|
38
|
+
}),
|
|
39
|
+
color: 'var(--boemly-colors-orange-500)',
|
|
33
40
|
},
|
|
34
|
-
[
|
|
35
|
-
|
|
36
|
-
text: formatMessage({
|
|
41
|
+
[CreditAvailability.SOON_CREDITS_AVAILABLE]: {
|
|
42
|
+
message: formatMessage({
|
|
37
43
|
id: 'components.creditsAvailableBadge.text.notYet',
|
|
38
44
|
}),
|
|
45
|
+
color: 'var(--boemly-colors-blue-500)',
|
|
39
46
|
},
|
|
40
47
|
};
|
|
41
48
|
|
|
42
49
|
const variant = variants[status];
|
|
43
50
|
|
|
44
51
|
return (
|
|
45
|
-
<
|
|
52
|
+
<Flex
|
|
53
|
+
justifyContent="flex-start"
|
|
46
54
|
as={href ? NextLink : undefined}
|
|
47
55
|
href={href}
|
|
48
|
-
colorScheme={variant.color}
|
|
49
|
-
width="fit-content"
|
|
50
56
|
>
|
|
51
|
-
{variant.
|
|
52
|
-
|
|
57
|
+
<Tag backgroundColor={variant.color} mt="2" mb="1">
|
|
58
|
+
<Info size={12} color="white" weight="fill" />
|
|
59
|
+
<Spacer width="1" />
|
|
60
|
+
<Text color="white" size="xsLowBold">
|
|
61
|
+
{variant.message}
|
|
62
|
+
</Text>
|
|
63
|
+
</Tag>
|
|
64
|
+
</Flex>
|
|
53
65
|
);
|
|
54
66
|
};
|
|
55
67
|
|
|
@@ -2,6 +2,6 @@ const messagesDe = {
|
|
|
2
2
|
'components.creditsAvailableBadge.text.yes': 'Credits verfügbar',
|
|
3
3
|
'components.creditsAvailableBadge.text.some': 'Einige verbleibende Credits',
|
|
4
4
|
'components.creditsAvailableBadge.text.no': 'Keine verbleibenden Credits',
|
|
5
|
-
'components.creditsAvailableBadge.text.notYet': '
|
|
5
|
+
'components.creditsAvailableBadge.text.notYet': 'Credits bald verfügbar',
|
|
6
6
|
};
|
|
7
7
|
export default messagesDe;
|
|
@@ -248,13 +248,9 @@ export const ProjectInfo: React.FC<ProjectInfoProps> = ({
|
|
|
248
248
|
<></>
|
|
249
249
|
)}
|
|
250
250
|
|
|
251
|
-
|
|
252
|
-
<
|
|
253
|
-
|
|
254
|
-
</Box>
|
|
255
|
-
) : (
|
|
256
|
-
<></>
|
|
257
|
-
)}
|
|
251
|
+
<Box mt="2">
|
|
252
|
+
<CreditsAvailableBadge status={project.creditAvailability} />
|
|
253
|
+
</Box>
|
|
258
254
|
</Container>
|
|
259
255
|
);
|
|
260
256
|
};
|
|
@@ -8,7 +8,13 @@ const fpmClient = setupCache(
|
|
|
8
8
|
baseURL: `${FPM_API_URI}/v1`,
|
|
9
9
|
paramsSerializer: (p) => qs.stringify(p, { encodeValuesOnly: true }),
|
|
10
10
|
timeout: 5000,
|
|
11
|
-
})
|
|
11
|
+
}),
|
|
12
|
+
{
|
|
13
|
+
ttl:
|
|
14
|
+
FPM_API_URI.includes('127.0.0.1') || FPM_API_URI.includes('localhost')
|
|
15
|
+
? 0
|
|
16
|
+
: 10 * 60 * 1000, // 10 minutes
|
|
17
|
+
}
|
|
12
18
|
);
|
|
13
19
|
|
|
14
20
|
export default fpmClient;
|
|
@@ -27,7 +27,7 @@ describe('The getPortfolioProjects function', () => {
|
|
|
27
27
|
expect(projects[0]).toStrictEqual({
|
|
28
28
|
...fpmProjectMock,
|
|
29
29
|
slug: strapiProjectMock.attributes.slug,
|
|
30
|
-
|
|
30
|
+
creditAvailability: fpmProjectMock.creditAvailability,
|
|
31
31
|
});
|
|
32
32
|
});
|
|
33
33
|
|
|
@@ -50,7 +50,7 @@ describe('The getPortfolioProjects function', () => {
|
|
|
50
50
|
expect(projects[0]).toStrictEqual({
|
|
51
51
|
...fpmProjectMock,
|
|
52
52
|
slug: strapiProjectMock.attributes.slug,
|
|
53
|
-
|
|
53
|
+
creditAvailability: fpmProjectMock.creditAvailability,
|
|
54
54
|
});
|
|
55
55
|
});
|
|
56
56
|
});
|
|
@@ -15,6 +15,7 @@ const getPortfolioProjects = async (
|
|
|
15
15
|
locale: string = 'en',
|
|
16
16
|
preview: boolean = false
|
|
17
17
|
): Promise<PortfolioProject[]> => {
|
|
18
|
+
const cache = preview ? false : undefined;
|
|
18
19
|
const params: Record<string, any> = {
|
|
19
20
|
populate: 'deep,6',
|
|
20
21
|
locale,
|
|
@@ -30,17 +31,16 @@ const getPortfolioProjects = async (
|
|
|
30
31
|
{ data: strapiProjectsLocalized },
|
|
31
32
|
{ data: strapiProjectsEnglish },
|
|
32
33
|
] = await Promise.all([
|
|
33
|
-
fpmClient.get<FPMProject[]>('/public/projects'),
|
|
34
|
+
fpmClient.get<FPMProject[]>('/public/projects', { cache }),
|
|
34
35
|
strapiClient.get<IStrapiResponse<IStrapiData<StrapiProject>[]>>(
|
|
35
36
|
'/projects',
|
|
36
|
-
{
|
|
37
|
-
params,
|
|
38
|
-
}
|
|
37
|
+
{ params, cache }
|
|
39
38
|
),
|
|
40
39
|
strapiClient.get<IStrapiResponse<IStrapiData<StrapiProject>[]>>(
|
|
41
40
|
'/projects',
|
|
42
41
|
{
|
|
43
42
|
params: { ...params, locale: FALLBACK_LOCALE },
|
|
43
|
+
cache,
|
|
44
44
|
}
|
|
45
45
|
),
|
|
46
46
|
]);
|
|
@@ -64,9 +64,6 @@ const getPortfolioProjects = async (
|
|
|
64
64
|
if (strapiProject?.attributes.slug) {
|
|
65
65
|
toReturn.slug = strapiProject.attributes.slug;
|
|
66
66
|
}
|
|
67
|
-
if (strapiProject?.attributes.creditsAvailable) {
|
|
68
|
-
toReturn.creditsAvailable = strapiProject?.attributes.creditsAvailable;
|
|
69
|
-
}
|
|
70
67
|
if (strapiProject?.attributes.thumbnail) {
|
|
71
68
|
toReturn.thumbnail = strapiProject?.attributes.thumbnail;
|
|
72
69
|
}
|
|
@@ -14,6 +14,7 @@ const getStaticPropsFromStrapi = async (
|
|
|
14
14
|
path: string,
|
|
15
15
|
{ locale = 'en', slug, preview = false, filters = {} }: Options
|
|
16
16
|
): Promise<AxiosResponse> => {
|
|
17
|
+
const cache = preview ? false : undefined;
|
|
17
18
|
const enrichedFilters: Record<string, string> = filters;
|
|
18
19
|
|
|
19
20
|
if (slug) {
|
|
@@ -31,7 +32,7 @@ const getStaticPropsFromStrapi = async (
|
|
|
31
32
|
params.publicationState = 'preview';
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
return strapiClient.get(path, { params });
|
|
35
|
+
return strapiClient.get(path, { params, cache });
|
|
35
36
|
};
|
|
36
37
|
|
|
37
38
|
export default getStaticPropsFromStrapi;
|
|
@@ -22,6 +22,7 @@ const getStrapiCollectionType = async <
|
|
|
22
22
|
key: K,
|
|
23
23
|
{ locale = 'en', preview = false, filters = {} }: Options
|
|
24
24
|
): Promise<IStrapiData<T>[]> => {
|
|
25
|
+
const cache = preview ? false : undefined;
|
|
25
26
|
const params: Record<string, any> = {
|
|
26
27
|
populate: 'deep,6',
|
|
27
28
|
locale: 'all',
|
|
@@ -35,7 +36,7 @@ const getStrapiCollectionType = async <
|
|
|
35
36
|
|
|
36
37
|
const { data } = await strapiClient.get<IStrapiResponse<IStrapiData<T>[]>>(
|
|
37
38
|
path,
|
|
38
|
-
{ params }
|
|
39
|
+
{ params, cache }
|
|
39
40
|
);
|
|
40
41
|
|
|
41
42
|
const localizedResponses = data.data.filter(
|
|
@@ -17,6 +17,7 @@ const getStrapiSingleType = async <T>(
|
|
|
17
17
|
path: string,
|
|
18
18
|
{ locale = 'en', preview = false, filters = {} }: Options
|
|
19
19
|
): Promise<IStrapiData<T>> => {
|
|
20
|
+
const cache = preview ? false : undefined;
|
|
20
21
|
const params: Record<string, any> = {
|
|
21
22
|
populate: 'deep,6',
|
|
22
23
|
locale,
|
|
@@ -31,13 +32,14 @@ const getStrapiSingleType = async <T>(
|
|
|
31
32
|
let response: AxiosResponse<IStrapiResponse<IStrapiData<T>>>;
|
|
32
33
|
|
|
33
34
|
try {
|
|
34
|
-
response = await strapiClient.get(path, { params });
|
|
35
|
+
response = await strapiClient.get(path, { params, cache });
|
|
35
36
|
return response.data.data;
|
|
36
37
|
} catch (error: any) {
|
|
37
38
|
if (error.isAxiosError && error.response?.status === 404) {
|
|
38
39
|
// Retry request with fallback locale
|
|
39
40
|
response = await strapiClient.get(path, {
|
|
40
41
|
params: { ...params, locale: STRAPI_FALLBACK_LOCALE },
|
|
42
|
+
cache,
|
|
41
43
|
});
|
|
42
44
|
|
|
43
45
|
return response.data.data;
|
|
@@ -8,7 +8,13 @@ const strapiClient = setupCache(
|
|
|
8
8
|
baseURL: `${STRAPI_URI}/api`,
|
|
9
9
|
paramsSerializer: (p) => qs.stringify(p, { encodeValuesOnly: true }),
|
|
10
10
|
timeout: 60_000,
|
|
11
|
-
})
|
|
11
|
+
}),
|
|
12
|
+
{
|
|
13
|
+
ttl:
|
|
14
|
+
STRAPI_URI.includes('127.0.0.1') || STRAPI_URI.includes('localhost')
|
|
15
|
+
? 0
|
|
16
|
+
: 10 * 60 * 1000, // 10 minutes
|
|
17
|
+
}
|
|
12
18
|
);
|
|
13
19
|
|
|
14
20
|
export default strapiClient;
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { StrapiImage } from '..';
|
|
2
|
-
import CreditsAvailableState from './CreditsAvailableState';
|
|
3
2
|
import FPMProject from './fpm/FPMProject';
|
|
4
3
|
|
|
5
4
|
interface PortfolioProject extends FPMProject {
|
|
@@ -7,7 +6,6 @@ interface PortfolioProject extends FPMProject {
|
|
|
7
6
|
slug?: string;
|
|
8
7
|
portfolioHost?: string;
|
|
9
8
|
thumbnail?: StrapiImage | null;
|
|
10
|
-
creditsAvailable?: CreditsAvailableState;
|
|
11
9
|
footerSubTitle?: string;
|
|
12
10
|
}
|
|
13
11
|
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import Issuer from './Issuer';
|
|
2
2
|
|
|
3
|
+
export enum CreditAvailability {
|
|
4
|
+
CREDITS_AVAILABLE = 'credits_available',
|
|
5
|
+
NO_CREDITS_AVAILABLE = 'no_credits_available',
|
|
6
|
+
SOME_CREDITS_AVAILABLE = 'some_credits_available',
|
|
7
|
+
SOON_CREDITS_AVAILABLE = 'soon_credits_available',
|
|
8
|
+
}
|
|
9
|
+
|
|
3
10
|
interface FPMProject {
|
|
4
11
|
id: string;
|
|
5
12
|
title: string;
|
|
@@ -33,6 +40,7 @@ interface FPMProject {
|
|
|
33
40
|
forecastedAmountYearly?: number;
|
|
34
41
|
riskBuffer?: number;
|
|
35
42
|
defaultIssuer?: Issuer;
|
|
43
|
+
creditAvailability: CreditAvailability;
|
|
36
44
|
|
|
37
45
|
createdAt: Date;
|
|
38
46
|
updatedAt: Date;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import CreditsAvailableState from '../CreditsAvailableState';
|
|
2
1
|
import Locale from '../Locale';
|
|
3
2
|
import IStrapi from './IStrapi';
|
|
4
3
|
import IStrapiData from './IStrapiData';
|
|
@@ -12,7 +11,6 @@ interface StrapiProject {
|
|
|
12
11
|
slug: string;
|
|
13
12
|
locale: Locale;
|
|
14
13
|
fpmProjectId?: string;
|
|
15
|
-
creditsAvailable?: CreditsAvailableState;
|
|
16
14
|
footerSubTitle?: string;
|
|
17
15
|
createdAt: string;
|
|
18
16
|
updatedAt: string;
|
package/src/rootMessages.de.ts
CHANGED
|
@@ -8,7 +8,6 @@ import portfolioDocumentsDownloadListMessagesDe from './components/portfolio/Doc
|
|
|
8
8
|
import projectFactsMessagesDe from './slices/ProjectFacts/messages.de';
|
|
9
9
|
import projectsMapMessagesDe from './slices/ProjectsMap/messages.de';
|
|
10
10
|
import portfolioProjectInfoMessagesDe from './components/portfolio/ProjectInfo/messages.de';
|
|
11
|
-
import portfolioProjectCardMessagesDe from './components/portfolio/PortfolioProjectCard/messages.de';
|
|
12
11
|
import portfolioSmallCheckoutMessagesDe from './components/portfolio/SmallCheckout/messages.de';
|
|
13
12
|
import shopCheckoutMessagesDe from './slices/ShopCheckout/messages.de';
|
|
14
13
|
import textCarouselMessagesDe from './slices/TextCarousel/messages.de';
|
|
@@ -22,7 +21,6 @@ const rootMessagesDe = {
|
|
|
22
21
|
//
|
|
23
22
|
...creditsAvailableBadgeMessagesDe,
|
|
24
23
|
...portfolioDocumentsDownloadListMessagesDe,
|
|
25
|
-
...portfolioProjectCardMessagesDe,
|
|
26
24
|
...portfolioProjectInfoMessagesDe,
|
|
27
25
|
...portfolioSmallCheckoutMessagesDe,
|
|
28
26
|
|
package/src/rootMessages.en.ts
CHANGED
|
@@ -8,7 +8,6 @@ import portfolioDocumentsDownloadListMessagesEn from './components/portfolio/Doc
|
|
|
8
8
|
import projectFactsMessagesEn from './slices/ProjectFacts/messages.en';
|
|
9
9
|
import projectsMapMessagesEn from './slices/ProjectsMap/messages.en';
|
|
10
10
|
import portfolioProjectInfoMessagesEn from './components/portfolio/ProjectInfo/messages.en';
|
|
11
|
-
import portfolioProjectCardMessagesEn from './components/portfolio/PortfolioProjectCard/messages.en';
|
|
12
11
|
import portfolioSmallCheckoutMessagesEn from './components/portfolio/SmallCheckout/messages.en';
|
|
13
12
|
import shopCheckoutMessagesEn from './slices/ShopCheckout/messages.en';
|
|
14
13
|
import textCarouselMessagesEn from './slices/TextCarousel/messages.en';
|
|
@@ -22,7 +21,6 @@ const rootMessagesEn = {
|
|
|
22
21
|
//
|
|
23
22
|
...creditsAvailableBadgeMessagesEn,
|
|
24
23
|
...portfolioDocumentsDownloadListMessagesEn,
|
|
25
|
-
...portfolioProjectCardMessagesEn,
|
|
26
24
|
...portfolioProjectInfoMessagesEn,
|
|
27
25
|
...portfolioSmallCheckoutMessagesEn,
|
|
28
26
|
|
|
@@ -3,7 +3,6 @@ import { StoryFn, Meta } from '@storybook/react';
|
|
|
3
3
|
|
|
4
4
|
import fpmProjectMock from '../../test/integrationMocks/fpmProjectMock';
|
|
5
5
|
import { storybookStrapiAvatarMock } from '../../test/storybookMocks/storybookStrapiMedia';
|
|
6
|
-
import CreditsAvailableState from '../../models/CreditsAvailableState';
|
|
7
6
|
import ProjectFacts from '.';
|
|
8
7
|
|
|
9
8
|
export default {
|
|
@@ -53,7 +52,7 @@ WithCheckout.args = {
|
|
|
53
52
|
|
|
54
53
|
export const FullProps = Template.bind({});
|
|
55
54
|
FullProps.args = {
|
|
56
|
-
project:
|
|
55
|
+
project: fpmProjectMock,
|
|
57
56
|
slice: {
|
|
58
57
|
projectId: fpmProjectMock.id,
|
|
59
58
|
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { render, screen } from '../../test/testUtils';
|
|
2
|
+
import { ProjectGridCardProps } from './ProjectGridCard';
|
|
3
|
+
import ProjectGridCard from '.';
|
|
4
|
+
import fpmProjectMock from '../../test/integrationMocks/fpmProjectMock';
|
|
5
|
+
import { strapiMediaMock } from '../../test/strapiMocks/strapiMedia';
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import messagesEn from '../../components/CreditsAvailableBadge/messages.en';
|
|
8
|
+
|
|
9
|
+
const defaultProps: ProjectGridCardProps = {
|
|
10
|
+
project: {
|
|
11
|
+
...fpmProjectMock,
|
|
12
|
+
slug: 'slug',
|
|
13
|
+
thumbnail: { img: { data: strapiMediaMock }, alt: 'Alt Text', id: 1 },
|
|
14
|
+
},
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const setup = (props = {}) => {
|
|
18
|
+
const combinedProps = { ...defaultProps, ...props };
|
|
19
|
+
render(<ProjectGridCard {...combinedProps} />);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
describe('The ProjectGridCard component', () => {
|
|
23
|
+
it('displays the project card', () => {
|
|
24
|
+
setup();
|
|
25
|
+
|
|
26
|
+
expect(screen.getByText(fpmProjectMock.title)).toBeInTheDocument();
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('displays the project thumbnail', () => {
|
|
30
|
+
setup();
|
|
31
|
+
|
|
32
|
+
expect(screen.getByRole('img')).toHaveProperty('alt', 'Alt Text');
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
it('displays the project area', () => {
|
|
36
|
+
setup();
|
|
37
|
+
|
|
38
|
+
expect(screen.getByText('140 ha')).toBeInTheDocument();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('displays the project location', () => {
|
|
42
|
+
setup();
|
|
43
|
+
|
|
44
|
+
expect(screen.getByText('Austria')).toBeInTheDocument();
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
it('displays the credits available badge', () => {
|
|
48
|
+
setup();
|
|
49
|
+
|
|
50
|
+
expect(
|
|
51
|
+
screen.getByText(messagesEn['components.creditsAvailableBadge.text.yes'])
|
|
52
|
+
).toBeInTheDocument();
|
|
53
|
+
});
|
|
54
|
+
});
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { Box, Container, Flex, Heading, Tag, Text } from 'boemly';
|
|
2
|
+
import React, { useContext } from 'react';
|
|
3
|
+
import Image from 'next/image';
|
|
4
|
+
import PortfolioProject from '../../models/PortfolioProject';
|
|
5
|
+
import { strapiMediaUrl } from '../..';
|
|
6
|
+
import { IntlContext } from 'react-intl';
|
|
7
|
+
import { FORMAT_AS_HECTARE_CONFIG } from '../../constants/formatter';
|
|
8
|
+
import CreditsAvailableBadge from '../../components/CreditsAvailableBadge';
|
|
9
|
+
|
|
10
|
+
export interface ProjectGridCardProps {
|
|
11
|
+
project: PortfolioProject;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const ProjectGridCard = ({
|
|
15
|
+
project,
|
|
16
|
+
}: ProjectGridCardProps): JSX.Element => {
|
|
17
|
+
const { formatNumber } = useContext(IntlContext);
|
|
18
|
+
|
|
19
|
+
return (
|
|
20
|
+
<Container>
|
|
21
|
+
<Flex flexDir="column" height="full">
|
|
22
|
+
{project.thumbnail && (
|
|
23
|
+
<Box borderRadius="xl" position="relative" height="36" mb="2">
|
|
24
|
+
<Image
|
|
25
|
+
src={strapiMediaUrl(project.thumbnail?.img, 'medium')}
|
|
26
|
+
alt={project.thumbnail?.alt}
|
|
27
|
+
fill
|
|
28
|
+
style={{
|
|
29
|
+
objectFit: project.thumbnail?.objectFit || 'cover',
|
|
30
|
+
borderRadius: 'var(--boemly-radii-xl)',
|
|
31
|
+
}}
|
|
32
|
+
/>
|
|
33
|
+
</Box>
|
|
34
|
+
)}
|
|
35
|
+
<Heading my="4" size="lg">
|
|
36
|
+
{project.title}
|
|
37
|
+
</Heading>
|
|
38
|
+
<Flex flexDir="row" gap="2">
|
|
39
|
+
<Tag>
|
|
40
|
+
<Text size="xsLowBold" color="gray.800">
|
|
41
|
+
{formatNumber(
|
|
42
|
+
(project.area || 0) / 10000,
|
|
43
|
+
FORMAT_AS_HECTARE_CONFIG
|
|
44
|
+
)}
|
|
45
|
+
</Text>
|
|
46
|
+
</Tag>
|
|
47
|
+
<Tag>
|
|
48
|
+
<Text size="xsLowBold" color="gray.800">
|
|
49
|
+
{project.location}
|
|
50
|
+
</Text>
|
|
51
|
+
</Tag>
|
|
52
|
+
</Flex>
|
|
53
|
+
<CreditsAvailableBadge status={project.creditAvailability} />
|
|
54
|
+
</Flex>
|
|
55
|
+
</Container>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
@@ -2,8 +2,8 @@ import React from 'react';
|
|
|
2
2
|
import { StoryFn, Meta } from '@storybook/react';
|
|
3
3
|
|
|
4
4
|
import ProjectsGrid from '.';
|
|
5
|
-
import portfolioProjectMock from '../../test/integrationMocks/portfolioProjectMock';
|
|
6
5
|
import { strapiProjectMock } from '../../test/strapiMocks/strapiProject';
|
|
6
|
+
import portfolioProjectMock from '../../test/integrationMocks/portfolioProjectMock';
|
|
7
7
|
|
|
8
8
|
export default {
|
|
9
9
|
title: 'slices/ProjectsGrid',
|
|
@@ -4,7 +4,6 @@ import ProjectsGrid from '.';
|
|
|
4
4
|
import { ProjectsGridProps } from './ProjectsGrid';
|
|
5
5
|
import fpmProjectMock from '../../test/integrationMocks/fpmProjectMock';
|
|
6
6
|
import { strapiMediaMock } from '../../test/strapiMocks/strapiMedia';
|
|
7
|
-
import CreditsAvailableState from '../../models/CreditsAvailableState';
|
|
8
7
|
import { strapiProjectMock } from '../../test/strapiMocks/strapiProject';
|
|
9
8
|
|
|
10
9
|
const defaultProps: ProjectsGridProps = {
|
|
@@ -18,7 +17,6 @@ const defaultProps: ProjectsGridProps = {
|
|
|
18
17
|
isPublic: true,
|
|
19
18
|
thumbnail: { img: { data: strapiMediaMock }, alt: 'Alt Text', id: 1 },
|
|
20
19
|
footerSubTitle: 'certified-123',
|
|
21
|
-
creditsAvailable: CreditsAvailableState.YES,
|
|
22
20
|
},
|
|
23
21
|
],
|
|
24
22
|
};
|
|
@@ -2,9 +2,11 @@ import React from 'react';
|
|
|
2
2
|
import { Box, DefaultSectionContainer, SimpleGrid, Wrapper } from 'boemly';
|
|
3
3
|
import Link from 'next/link';
|
|
4
4
|
import { MEDIUM_TRANSITION_DURATION } from '../../constants/animations';
|
|
5
|
+
import ProjectGridCard from '../ProjectGridCard';
|
|
5
6
|
import PortfolioProject from '../../models/PortfolioProject';
|
|
6
|
-
import
|
|
7
|
-
import
|
|
7
|
+
import IStrapi from '../../models/strapi/IStrapi';
|
|
8
|
+
import IStrapiData from '../../models/strapi/IStrapiData';
|
|
9
|
+
import StrapiProject from '../../models/strapi/StrapiProject';
|
|
8
10
|
|
|
9
11
|
export interface ProjectsGridProps {
|
|
10
12
|
slice: {
|
|
@@ -65,7 +67,7 @@ export const ProjectsGrid: React.FC<ProjectsGridProps> = ({
|
|
|
65
67
|
transition={`box-shadow ease ${MEDIUM_TRANSITION_DURATION}s`}
|
|
66
68
|
_hover={{ boxShadow: 'lg' }}
|
|
67
69
|
>
|
|
68
|
-
<
|
|
70
|
+
<ProjectGridCard project={project} />
|
|
69
71
|
</Box>
|
|
70
72
|
</ConditionalWrapper>
|
|
71
73
|
))}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { fireEvent, render, screen, waitFor } from '../../test/testUtils';
|
|
3
|
-
import CreditsAvailableState from '../../models/CreditsAvailableState';
|
|
4
3
|
import MapMarker, { MapMarkerProps } from './MapMarker';
|
|
5
4
|
import messagesEn from './messages.en';
|
|
5
|
+
import { CreditAvailability } from '../../models/fpm/FPMProject';
|
|
6
6
|
|
|
7
7
|
const defaultProps: MapMarkerProps = {
|
|
8
8
|
title: 'Project title',
|
|
9
9
|
portfolioHost: '',
|
|
10
10
|
isPublic: true,
|
|
11
|
+
creditAvailability: CreditAvailability.CREDITS_AVAILABLE,
|
|
11
12
|
};
|
|
12
13
|
|
|
13
14
|
const setup = (props: Partial<MapMarkerProps> = {}) => {
|
|
@@ -88,7 +89,7 @@ describe('The MapMarker component', () => {
|
|
|
88
89
|
|
|
89
90
|
it('renders the credit availability if it is defined', () => {
|
|
90
91
|
setup({
|
|
91
|
-
|
|
92
|
+
creditAvailability: CreditAvailability.CREDITS_AVAILABLE,
|
|
92
93
|
});
|
|
93
94
|
|
|
94
95
|
fireEvent.mouseEnter(screen.getByTestId('mapmarker-pin'));
|