update
This commit is contained in:
parent
afb278ad87
commit
7611c41c67
@ -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">
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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
@ -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>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
@ -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));
|
||||
@ -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));
|
||||
@ -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;
|
||||
Loading…
x
Reference in New Issue
Block a user