Skip to content

Commit

Permalink
Merge pull request #97 from fac30/style/next-actions
Browse files Browse the repository at this point in the history
style: next actions
  • Loading branch information
maxitect authored Dec 17, 2024
2 parents 5627786 + 83e0c87 commit 83d9495
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 89 deletions.
111 changes: 61 additions & 50 deletions src/app/needs/next-actions/components/NextActionsDisplay.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,20 @@ export interface NextActionDocument {
export default function NextActionsDisplay() {
const database = useDatabase();
const [highlightedNeeds, setHighlightedNeeds] = useState<NeedDocument[]>([]);
const [relatedNextActions, setRelatedNextActions] = useState<NextActionDocument[]>([]);
const [relatedNextActions, setRelatedNextActions] = useState<
NextActionDocument[]
>([]);
const [chainEnd, setChainEnd] = useState(0);
const [actionState, setActionState] = useState(0);

useEffect(() => { /* Fetch Data */
useEffect(() => {
/* Fetch Data */
async function fetchData() {
const needsDocs = await database.getFromDb("needs");
const allNeeds = needsDocs.map(doc => doc.toJSON() as NeedDocument);
const allNeeds = needsDocs.map((doc) => doc.toJSON() as NeedDocument);
const now = new Date();

const filteredNeeds = allNeeds.filter(need => {
const filteredNeeds = allNeeds.filter((need) => {
const expiry = new Date(need.selectedExpiry);
return expiry > now && need.priority && need.priority.order > 0;
});
Expand All @@ -52,15 +55,13 @@ export default function NextActionsDisplay() {
const nextActionsDocs = await database.getFromDb("next_actions");

const allNextActions = nextActionsDocs.map(
doc => doc.toJSON() as NextActionDocument
(doc) => doc.toJSON() as NextActionDocument
);

const highlightedNeedIds = new Set(filteredNeeds.map(
need => need.id
));
const highlightedNeedIds = new Set(filteredNeeds.map((need) => need.id));

const filteredNextActions = allNextActions.filter(
action => highlightedNeedIds.has(action.need)
const filteredNextActions = allNextActions.filter((action) =>
highlightedNeedIds.has(action.need)
);

setRelatedNextActions(filteredNextActions);
Expand All @@ -73,28 +74,31 @@ export default function NextActionsDisplay() {
if (highlightedNeeds.length === 0) return [];

const needsWithPriority = highlightedNeeds.filter(
need => need.priority && need.priority.order
(need) => need.priority && need.priority.order
);

const sortedNeeds = needsWithPriority.sort((a, b) =>
a.priority!.order - b.priority!.order
const sortedNeeds = needsWithPriority.sort(
(a, b) => a.priority!.order - b.priority!.order
);

const groupsMap: Record<number, {
priority: {
order: number;
name: string;
};
needs: NeedDocument[]
}> = {};
const groupsMap: Record<
number,
{
priority: {
order: number;
name: string;
};
needs: NeedDocument[];
}
> = {};

for (const need of sortedNeeds) {
const order = need.priority!.order;

if (!groupsMap[order]) {
groupsMap[order] = {
priority: need.priority!,
needs: []
needs: [],
};
}

Expand All @@ -105,7 +109,7 @@ export default function NextActionsDisplay() {
}, [highlightedNeeds]);

const getActionsForNeed = (needId: string) => {
return relatedNextActions.filter(action => action.need === needId);
return relatedNextActions.filter((action) => action.need === needId);
};

const onToggleAction = async (action: NextActionDocument) => {
Expand All @@ -115,7 +119,7 @@ export default function NextActionsDisplay() {
if (highlighted) {
const updatedTimestamps = [...action.selectedTimestamps];
updatedTimestamps.pop();

await database.updateDocument(
collectionName,
action.id,
Expand All @@ -132,10 +136,15 @@ export default function NextActionsDisplay() {
} else {
// Highlight action:
// Add new selectedTimestamp
const updatedTimestamps = [...action.selectedTimestamps, new Date().toISOString()];
const updatedTimestamps = [
...action.selectedTimestamps,
new Date().toISOString(),
];

// Find the parent need to copy its selectedExpiry
const parentNeed = highlightedNeeds.find((need) => need.id === action.need);
const parentNeed = highlightedNeeds.find(
(need) => need.id === action.need
);
if (!parentNeed) {
console.error("Parent need not found for action:", action);
return;
Expand All @@ -156,7 +165,7 @@ export default function NextActionsDisplay() {
);
}

setChainEnd(prev => prev + 1);
setChainEnd((prev) => prev + 1);
};

const handleAddAction = async (newAction: string, need: NeedDocument) => {
Expand All @@ -168,48 +177,51 @@ export default function NextActionsDisplay() {
selectedTimestamps: [],
selectedExpiry: new Date().toISOString(),
timestamp: new Date().toISOString(),
}
};
try {
await database.addToDb("next_actions", newActionDocument);
console.log(`Action Created: ${newActionDocument.name}`);
} catch (error) {
console.error("Error creating Action:", error);
}
setActionState(prev => prev + 1);

setActionState((prev) => prev + 1);
}
};

return (
<div className="w-11/12 m-auto">
{ priorityGroups.length === 0 ?
(<p className="mb-5">
You have no unmet needs selected. Review which needs might be unmet before we can recommend next actions to meet them.
</p>) :
(priorityGroups.map((group, i) => (
{priorityGroups.length === 0 ? (
<p className="mb-5">
You have no unmet needs selected. Review which needs might be unmet
before we can recommend next actions to meet them.
</p>
) : (
priorityGroups.map((group, i) => (
<div key={i} className="mb-6">
<h3
className={clsx(
"text-xl font-bold mb-2",
{"text-twd-cube-red" : group.priority.order === 1 },
{"text-twd-cube-yellow" : group.priority.order === 2},
{"text-twd-cube-blue" : group.priority.order === 3},
{"text-twd-cube-green" : group.priority.order === 4}
{ "text-twd-cube-red": group.priority.order === 1 },
{ "text-twd-cube-yellow": group.priority.order === 2 },
{ "text-twd-cube-blue": group.priority.order === 3 },
{ "text-twd-cube-green": group.priority.order === 4 }
)}
>
{changeCase(group.priority.name, "sentence")}
</h3>

{group.needs.map((need) => {
const actions = getActionsForNeed(need.id);

return (
<div key={need.id} className="ml-4 mb-4">
<h4 className="font-semibold">
To meet a need for {changeCase(need.name, "lower")}, which actions can you take next?
<div key={need.id}>
<h4 className="font-normal mb-4">
To meet a need for {changeCase(need.name, "lower")}, which
actions can you take next?
</h4>

{ actions.length > 0 ? (
{actions.length > 0 ? (
<NextActionsSection
need={need}
actions={actions}
Expand All @@ -220,14 +232,13 @@ export default function NextActionsDisplay() {
<p className="text-sm text-gray-500 ml-6">
No next actions available for this need.
</p>
)
}
</div>
)}
</div>
);
})}
</div>
)))
}
))
)}
</div>
);
}
}
85 changes: 46 additions & 39 deletions src/app/needs/next-actions/components/NextActionsSection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,51 +24,58 @@ export default function NextActionsSection({
const [newAction, setNewAction] = useState<string>("");

const handleInputChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setNewAction(e.target.value)
setNewAction(e.target.value);
};

const handleSubmitAction = async () => {
await handleAddAction(newAction, need);
setModalOpen(false);
}
};

return ( <>
<div className="ml-4 mb-6">
{actions.map((action) => {
const highlighted = new Date(action.selectedExpiry) > new Date();
return (
<>
<div className="mb-6 flex gap-5 flex-wrap">
{actions.map((action) => {
const highlighted = new Date(action.selectedExpiry) > new Date();

return (<Button key={action.id}
label={action.name}
className={ highlighted ?
"bg-twd-primary-purple text-black" :
"bg-gray-600 text-white"
}
onClick={() => onToggleAction(action)}
/>);
})}
return (
<Button
key={action.id}
label={action.name}
className={
highlighted
? "bg-twd-primary-purple text-black font-normal"
: "bg-gray-600 text-white font-normal"
}
onClick={() => onToggleAction(action)}
/>
);
})}

<button onClick={() => setModalOpen(true)}
className="flex justify-center items-center"
aria-label="Add Action"
>
<PlusCircleIcon className="w-7 m-auto" />
</button>
</div>
<button
onClick={() => setModalOpen(true)}
className="flex justify-center items-center"
aria-label="Add Action"
>
<PlusCircleIcon className="w-7 m-auto" />
</button>
</div>

<Modal title="Add a New Action"
inputModal={true}
modalOpen={modalOpen}
placeholder="What action might help meet this need?"
handleInputChange={handleInputChange}
forwardButton={{ label: "Add",
action: handleSubmitAction,
}}
backButton={{ label: "Cancel",
action: () => {
setNewAction("");
setModalOpen(false);
},
}}
/>
</> );
}
<Modal
title="Add a New Action"
inputModal={true}
modalOpen={modalOpen}
placeholder="What action might help meet this need?"
handleInputChange={handleInputChange}
forwardButton={{ label: "Add", action: handleSubmitAction }}
backButton={{
label: "Cancel",
action: () => {
setNewAction("");
setModalOpen(false);
},
}}
/>
</>
);
}

0 comments on commit 83d9495

Please sign in to comment.