🔨 - [react-personal-anniversary-counter] built sample

This commit is contained in:
Dan Toft 2023-12-09 17:47:58 +01:00
parent aa06723974
commit 182fc19319
6 changed files with 141 additions and 16 deletions

View File

@ -12,31 +12,31 @@
"test": "gulp test"
},
"dependencies": {
"tslib": "2.3.1",
"react": "17.0.1",
"react-dom": "17.0.1",
"@fluentui/react": "^8.106.4",
"@microsoft/sp-core-library": "1.18.2",
"@microsoft/sp-component-base": "1.18.2",
"@microsoft/sp-core-library": "1.18.2",
"@microsoft/sp-lodash-subset": "1.18.2",
"@microsoft/sp-office-ui-fabric-core": "1.18.2",
"@microsoft/sp-property-pane": "1.18.2",
"@microsoft/sp-webpart-base": "1.18.2",
"@microsoft/sp-lodash-subset": "1.18.2",
"@microsoft/sp-office-ui-fabric-core": "1.18.2"
"react": "17.0.1",
"react-dom": "17.0.1",
"tslib": "2.3.1"
},
"devDependencies": {
"@microsoft/rush-stack-compiler-4.7": "0.1.0",
"@rushstack/eslint-config": "2.5.1",
"@microsoft/eslint-plugin-spfx": "1.18.2",
"@microsoft/eslint-config-spfx": "1.18.2",
"@microsoft/eslint-plugin-spfx": "1.18.2",
"@microsoft/rush-stack-compiler-4.7": "0.1.0",
"@microsoft/sp-build-web": "1.18.2",
"@microsoft/sp-module-interfaces": "1.18.2",
"@rushstack/eslint-config": "2.5.1",
"@types/react": "17.0.45",
"@types/react-dom": "17.0.17",
"@types/webpack-env": "~1.15.2",
"ajv": "^6.12.5",
"eslint": "8.7.0",
"gulp": "4.0.2",
"typescript": "4.7.4",
"@types/react": "17.0.45",
"@types/react-dom": "17.0.17",
"eslint-plugin-react-hooks": "4.3.0",
"@microsoft/sp-module-interfaces": "1.18.2"
"gulp": "4.0.2",
"typescript": "4.7.4"
}
}

View File

@ -0,0 +1,19 @@
@import '~@fluentui/react/dist/sass/References.scss';
.wrapper {
background:
radial-gradient(circle at 100% 100%, #ffffff 0, #ffffff 6px, transparent 6px) 0% 0%/11px 11px no-repeat,
radial-gradient(circle at 0 100%, #ffffff 0, #ffffff 6px, transparent 6px) 100% 0%/11px 11px no-repeat,
radial-gradient(circle at 100% 0, #ffffff 0, #ffffff 6px, transparent 6px) 0% 100%/11px 11px no-repeat,
radial-gradient(circle at 0 0, #ffffff 0, #ffffff 6px, transparent 6px) 100% 100%/11px 11px no-repeat,
linear-gradient(#ffffff, #ffffff) 50% 50% / calc(100% - 10px) calc(100% - 22px) no-repeat,
linear-gradient(#ffffff, #ffffff) 50% 50% / calc(100% - 22px) calc(100% - 10px) no-repeat,
linear-gradient(325deg, #dfc5e4 0%, #cae4f0 100%);
border-radius: 11px;
padding: 15px;
box-sizing: content-box;
align-items: "center";
display: "flex";
flex-direction: "column";
}

View File

@ -1,11 +1,49 @@
import * as React from 'react';
import useLocalStorage from '../hooks/useLocalStorage';
import { DatePicker, PrimaryButton, Stack, Text } from '@fluentui/react';
import styles from './PersonalAnniversary.module.scss';
export interface IPersonalAnniversaryProps {}
export interface IPersonalAnniversaryProps { }
export const PersonalAnniversary: React.FunctionComponent<IPersonalAnniversaryProps> = (props: React.PropsWithChildren<IPersonalAnniversaryProps>) => {
const [date, setDate] = useLocalStorage<{ AnniversaryDate: Date }>('personalAnniversary', null)
const [tempDate, setTempDate] = React.useState<Date>(null)
if (date === null)
return <>
<div className={styles.wrapper}>
<DatePicker
label="When did you join the company?"
onSelectDate={(date) => setTempDate(date)}
value={tempDate}
formatDate={(date) => {
if (date === null)
return ''
return date.toLocaleDateString()
}}
isRequired={true}
/>
<PrimaryButton
text="Save"
onClick={() => setDate({ AnniversaryDate: tempDate })}
disabled={tempDate === null}
/>
</div>
</>
const DateDiff: number = new Date().getTime() - date.AnniversaryDate.getTime()
return (
<>
<div className={styles.wrapper} >
<Text variant="xLarge">You&apos; ve been working here for:</Text>
<Stack tokens={{ childrenGap: 5 }} styles={{ root: { marginTop: "2em", alignItems: "center", } }}>
<Text variant='large'><b>{Math.floor(DateDiff / (1000 * 3600 * 24 * 365))}</b> Years</Text>
<Text variant='large'><b>{Math.floor(DateDiff / ((1000 * 3600 * 24 * 365) / 12))}</b> Months</Text>
<Text variant='large'><b>{Math.floor(DateDiff / (1000 * 3600 * 24))}</b> Days</Text>
</Stack>
</div>
</>
);
};

View File

@ -0,0 +1,20 @@
import { useState } from 'react';
import { ObjectHelper } from '../utils/Objecthelper';
export default function useLocalStorage<T>(key: string, initialValue?: T): [T, (value: T) => void] {
const [value, setValue] = useState<T>(() => {
const item = window.localStorage.getItem(key);
return item ? ObjectHelper.ParseItem(JSON.parse(item)) : initialValue;
});
const setItem: (newValue: T) => void = (newValue: T) => {
window.localStorage.setItem(key, JSON.stringify(newValue));
setValue(newValue);
};
return [
value, setItem
];
}

View File

@ -0,0 +1,4 @@
export interface IPersonalAnniversary {
Title: string;
AnniversaryDate: Date;
}

View File

@ -0,0 +1,44 @@
/* eslint-disable */
export namespace ObjectHelper {
const RemoveODataProperties = (obj: any) => {
for (let prop of Object.keys(obj))
if (prop.indexOf("odata.") == 0)
delete obj[prop];
return obj;
}
const ISO_8601_FULL = /^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(\.\d+)?(([+-]\d\d:\d\d)|Z)?$/i
const isISO8601 = (str: string) => (str + "").match(ISO_8601_FULL);
const ParseAllDates = (obj: any) => {
for (let prop of Object.keys(obj))
if (isISO8601(obj[prop]))
obj[prop] = new Date(obj[prop]);
return obj;
}
const RemoveProps: string[] = ["Attachments", "ComplianceAssetId", "FileSystemObjectType", "GUID", "ID", "OData__ColorTag", "OData__UIVersionString", "ServerRedirectedEmbedUri", "ServerRedirectedEmbedUrl"];
const RemoveDefaultFields = (obj: any) => {
for (let prop of RemoveProps)
delete obj[prop];
return obj;
}
export const ParseItem: <T>(item: T) => T = <T>(item: any) => {
if (Array.isArray(item)) {
for (let i of item) {
i = RemoveODataProperties(i);
i = ParseAllDates(i);
i = RemoveDefaultFields(i);
}
} else {
item = RemoveODataProperties(item);
item = ParseAllDates(item);
item = RemoveDefaultFields(item);
}
return item;
}
}