This commit is contained in:
silas 2021-12-12 18:06:33 +01:00
parent afb278ad87
commit 7611c41c67
9 changed files with 171 additions and 9412 deletions

View File

@ -9,7 +9,7 @@
<meta name="viewport" content="initial-scale=1, width=device-width, viewport-fit=cover">
<meta name="color-scheme" content="light dark">
<!-- <link rel="stylesheet" href="css/index.css">-->
<title>Hello World</title>
<title>PrayerCircle</title>
</head>
<!--<body class="flat-design">-->
<body class="material-design">

View File

@ -2,7 +2,7 @@ import * as React from 'react';
import { useCallback, useMemo } from 'react';
import { useAppDispatch, useAppSelector } from '../Store/reduxHooks';
import { selectMemberIds, setWeek } from './prayerCircleSlice';
import { Button, Flex, Grow, Table } from 'react-bootstrap-mobile';
import { Body, Button, Column, ColumnCellData, Flex, Grow, Table } from 'react-bootstrap-mobile';
import { PrayerCircleCalculator } from './PrayerCircleCalculator';
export type PartnerTableProps = {};
@ -16,8 +16,8 @@ function PartnerTable({}: PartnerTableProps) {
const usePartners = useAppSelector((state) => state.prayerCircle.usePartners);
const dispatch = useAppDispatch();
const columnsWeek = useMemo(
() => [
const columnsWeek = useMemo(() => {
const columns: Column<string> = [
{
Header: 'Partner 1',
accessor: 'partner1', // accessor is the "key" in the data
@ -25,13 +25,55 @@ function PartnerTable({}: PartnerTableProps) {
{
Header: 'Partner 2',
accessor: 'partner2',
width: '50%',
},
],
[]
);
];
if (!usePartners) {
columns.splice(1, 0, {
Header: '',
id: 'prayingTitles',
Cell: () => (
<>
<Body block={true}>Ich bete für</Body>
<Body block={true} prio="secondary" size="small">
Für mich betet
</Body>
</>
),
});
// columns[0].Cell = (cellData: ColumnCellData<string>) => {
// const partner = cellData.value;
// console.log('cellData', cellData);
// return (
// <div>
// <Body>{partner}</Body>
// <span>
// {/* <Body>Ich bete für</Body> */}
// <Body prio="secondary" size="small">
// Für mich betet
// </Body>
// </span>
// </div>
// );
// };
const columnsWeekdays = useMemo(
() => [
columns[2].Cell = ({ cell: { column, row }, value: partner }: ColumnCellData<string>) => {
const other = row.original[`${column.id}Other`];
return (
<>
<Body block={true}>{partner}</Body>
<Body block={true} prio="secondary" size="small">
{other}
</Body>
</>
);
};
}
return columns;
}, [usePartners]);
const columnsWeekdays = useMemo(() => {
const columns: Column<string> = [
{
Header: 'Person',
accessor: 'person', // accessor is the "key" in the data
@ -64,9 +106,44 @@ function PartnerTable({}: PartnerTableProps) {
Header: 'So',
accessor: 'day6',
},
],
[]
);
];
if (!usePartners) {
columns[0].Cell = ({ value: partner }: ColumnCellData<string>) => {
return (
<Flex>
<Grow>{partner}</Grow>
<Grow>
<Body block={true}>Ich bete für</Body>
<Body block={true} prio="secondary" size="small">
Für mich betet
</Body>
</Grow>
</Flex>
);
};
const renderFunction = (cellData: ColumnCellData<string>) => {
const partner = cellData.value;
const other = cellData.cell.row.original[`${cellData.cell.column.id}Other`];
return (
<>
<Body block={true}>{partner}</Body>
<Body block={true} prio="secondary" size="small">
{other}
</Body>
</>
);
};
columns[1].Cell = renderFunction;
columns[2].Cell = renderFunction;
columns[3].Cell = renderFunction;
columns[4].Cell = renderFunction;
columns[5].Cell = renderFunction;
columns[6].Cell = renderFunction;
columns[7].Cell = renderFunction;
}
return columns;
}, [usePartners]);
// States
@ -79,45 +156,53 @@ function PartnerTable({}: PartnerTableProps) {
// Effects
// Other
const partnerTable = useMemo(
const [partnerTable, invertedPartnerTable] = useMemo(
() => PrayerCircleCalculator.generateTableFor(membersIds, usePartners),
[membersIds, usePartners]
);
if (!partnerTable || membersIds.length === 0) {
if (!partnerTable || !invertedPartnerTable || membersIds.length === 0) {
return null;
}
const partnerTableNames = partnerTable.map((partnerColumn) => {
// console.log(partnerTable, invertedPartnerTable);
const partnerTableNames = partnerTable.map((partnerColumn, index) => {
return Object.keys(partnerColumn).map((id) => {
const name = members[id]?.name ?? id;
const partnerName = members[partnerColumn[id]]?.name ?? partnerColumn[id];
return [name, partnerName];
}) as [string, string][];
const otherPartnerName = members[invertedPartnerTable[index][id]]?.name ?? invertedPartnerTable[index][id];
return [name, partnerName, otherPartnerName];
}) as [string, string, string][];
});
let data: Record<string, string>[] = [];
if (!useWeekdays) {
const column = partnerTableNames[week % partnerTableNames.length];
data = column.map(([name1, name2]) => ({
data = column.map(([name1, name2, name3]) => ({
partner1: name1,
partner2: name2,
partner2Other: name3,
}));
} else {
data = [];
for (let i = 0; i < 7; i++) {
const column = partnerTableNames[(week * 7 + i) % partnerTableNames.length];
column.forEach(([name1, name2], index) => {
const colIndex = (week * 7 + i) % partnerTableNames.length;
const column = partnerTableNames[colIndex];
column.forEach(([person, partner1, partner2], index) => {
if (!data[index]) {
data[index] = { person: name1 };
data[index] = { person };
}
data[index][`day${i}`] = name2;
data[index][`day${i}`] = partner1;
data[index][`day${i}Other`] = partner2;
});
}
}
const columns = useWeekdays ? columnsWeekdays : columnsWeek;
// Render Functions
return (
<>
<Flex>

View File

@ -1,8 +1,6 @@
import * as React from 'react';
import { Sites, useSites, useTopBar } from 'cordova-sites';
import { useState } from 'react';
import { Sites, useTopBar } from 'cordova-sites';
import { MemberList } from './MemberList';
import { Settings } from '../Settings/Settings';
import { Card } from 'react-bootstrap-mobile';
import { PartnerTable } from './PartnerTable';
import { Col, Row } from 'react-bootstrap';
@ -12,7 +10,6 @@ export type PrayerCircleProps = {};
function PrayerCircle({}: PrayerCircleProps) {
// Variables
const sites = useSites();
// States
@ -23,14 +20,6 @@ function PrayerCircle({}: PrayerCircleProps) {
// Effects
useTopBar({
title: 'Prayercircle',
rightButtons: [
{
title: 'Settings',
action: () => {
sites?.startSite(Settings);
},
},
],
});
// Other
@ -39,13 +28,13 @@ function PrayerCircle({}: PrayerCircleProps) {
return (
<>
<Row lg={2} sm={1}>
<Row lg={3} md={2} sm={1}>
<Col>
<Card fullHeight={true}>
<PrayerCircleSettings />
</Card>
</Col>
<Col className="order-lg-first">
<Col className="order-md-first" md={6} lg={8}>
<Card noPaddingHeight={true}>
<MemberList />
</Card>

View File

@ -4251,9 +4251,12 @@ export class PrayerCircleCalculator {
console.log('TABLES', JSON.stringify(tables));
}
static generateTableFor(memberIds: string[], usePartners = true) {
static generateTableFor(
memberIds: string[],
usePartners = true
): [false, false] | [Record<string, string>[], Record<string, string>[]] {
if (memberIds.length === 0) {
return [];
return [[], []];
}
memberIds = memberIds.slice();
@ -4269,15 +4272,11 @@ export class PrayerCircleCalculator {
}
if (numberTable === false) {
return false;
return [false, false];
}
return numberTable.map((column) => {
const idColumn: Record<string, string> = {};
Object.keys(column).forEach((index) => {
idColumn[memberIds[Number(index)]] = memberIds[column[Number(index)]];
});
return idColumn;
});
const table = PrayerCircleCalculator.inflateTable(memberIds, numberTable);
const invertedTable = PrayerCircleCalculator.getInvertedChainTableFor(table);
return [table, invertedTable];
}
static generateTable(numPrayers: number): Record<number, number>[] | false {
@ -4387,6 +4386,10 @@ export class PrayerCircleCalculator {
}
private static generateChainTableFor(numPrayers: number) {
if (numPrayers < 2) {
return false;
}
const possiblePartnersBaseArray: number[] = [];
for (let i = 0; i < numPrayers; i++) {
possiblePartnersBaseArray.push(i);
@ -4401,6 +4404,35 @@ export class PrayerCircleCalculator {
for (let i = 0; i < numPrayers - 1; i++) {
table.push({});
}
possiblePartnersBaseArray.forEach((member, index) => {
const otherMembers = possiblePartners[member];
for (let i = 0; i < numPrayers - 1; i++) {
table[i][member] = otherMembers[(index + i) % otherMembers.length];
}
});
return table;
}
static getInvertedChainTableFor(table: Record<string, string>[]) {
return table.map((column) => {
const invertedColumn: Record<string, string> = {};
Object.keys(column).forEach((id1) => {
invertedColumn[column[id1]] = id1;
});
return invertedColumn;
});
}
private static inflateTable(memberIds: string[], table: Column[]) {
return table.map((column) => {
const idColumn: Record<string, string> = {};
Object.keys(column).forEach((index) => {
idColumn[memberIds[Number(index)]] = memberIds[column[Number(index)]];
});
return idColumn;
});
}
}

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@ import { Checkbox, Switch } from 'react-bootstrap-mobile';
import { useCallback } from 'react';
import { useAppDispatch, useAppSelector } from '../Store/reduxHooks';
import { setUsePartners, setUseWeekdays } from './prayerCircleSlice';
import { setDesign } from '../Settings/settingsSlice';
export type PrayerCircleSettingsProps = {};
@ -11,6 +12,7 @@ function PrayerCircleSettings({}: PrayerCircleSettingsProps) {
const dispatch = useAppDispatch();
const useWeekdays = useAppSelector((store) => store.prayerCircle.useWeekdays ?? false);
const usePartners = useAppSelector((store) => store.prayerCircle.usePartners ?? true);
const design = useAppSelector((state) => state.settings.design);
// States
@ -19,6 +21,13 @@ function PrayerCircleSettings({}: PrayerCircleSettingsProps) {
// Callbacks
const onChangeUseWeekdays = useCallback(({ target: { checked } }) => dispatch(setUseWeekdays(checked)), [dispatch]);
const onChangeUsePartners = useCallback(({ target: { checked } }) => dispatch(setUsePartners(checked)), [dispatch]);
const toggleThemeCallback = useCallback(() => {
if (design === 'material') {
dispatch(setDesign('flat'));
} else {
dispatch(setDesign('material'));
}
}, [dispatch, design]);
// Effects
@ -33,6 +42,16 @@ function PrayerCircleSettings({}: PrayerCircleSettingsProps) {
</Switch>
<br />
<Checkbox label="Benutze Wochentage" checked={useWeekdays} onChange={onChangeUseWeekdays} />
<br />
<Switch
id="switchTheme"
checked={design === 'flat'}
preLabel="android"
isDual={true}
onChange={toggleThemeCallback}
>
ios
</Switch>
</>
);
}

View File

@ -1,49 +0,0 @@
import * as React from 'react';
import { Sites, useTopBar } from 'cordova-sites';
import { FunctionComponent, useCallback } from 'react';
import { Button, Switch } from 'react-bootstrap-mobile';
import { useAppDispatch, useAppSelector } from '../Store/reduxHooks';
import { setDesign } from './settingsSlice';
type Props = {};
export const Settings: FunctionComponent<Props> = React.memo(({}) => {
// Variables
const design = useAppSelector((state) => state.settings.design);
const isActive = design === 'flat';
const dispatch = useAppDispatch();
// States
// Refs
// Callbacks
const toggleThemeCallback = useCallback(() => {
if (design === 'material') {
dispatch(setDesign('flat'));
} else {
dispatch(setDesign('material'));
}
}, [dispatch, design]);
// Effects
useTopBar({
title: 'Settings',
});
// Other
// Render Functions
return (
<>
<br />
<br />
<Switch id="switchTheme" checked={isActive} preLabel="android" isDual={true} onChange={toggleThemeCallback}>
ios
</Switch>
<Button onClick={toggleThemeCallback}>Change Theme</Button>
</>
);
});
Sites.addInitialization((app) => app.addDeepLink('/Settings', Settings));

View File

@ -1,46 +0,0 @@
import * as React from 'react';
import { Sites, useSites, useTopBar } from 'cordova-sites';
import { FunctionComponent } from 'react';
import { Settings } from '../Settings/Settings';
import { Input, Switch } from 'react-bootstrap-mobile';
type Props = {};
export const TaskList: FunctionComponent<Props> = React.memo(({}) => {
// Variables
const sites = useSites();
// States
// Refs
// Callbacks
// Effects
useTopBar({
title: 'TaskList',
rightButtons: [
{
title: 'Settings',
action: () => {
sites?.startSite(Settings);
},
},
],
});
// Other
// Render Functions
return (
<>
<br />
<br />
<Input label="test" placeholder="Your Text" />
<Switch id="switchTheme" isDual={false} preLabel="android" onChange={(e) => console.log(e.target.checked)}>
ios
</Switch>
</>
);
});
Sites.addInitialization((app) => app.addDeepLink('/TaskList', TaskList));

View File

@ -1,22 +0,0 @@
import { createSlice } from '@reduxjs/toolkit';
export const tasksSlice = createSlice({
name: 'tasks',
initialState: {
value: 0,
},
reducers: {
increment: (state) => {
state.value += 1;
},
decrement: (state) => {
state.value -= 1;
},
incrementByAmount: (state, action) => {
state.value += action.payload;
},
},
});
export const { increment, decrement, incrementByAmount } = tasksSlice.actions;
export default tasksSlice.reducer;