diff --git a/packages/api/prisma/migrations/20240202093215_api/migration.sql b/packages/api/prisma/migrations/20240202093215_api/migration.sql new file mode 100644 index 00000000..44e4178d --- /dev/null +++ b/packages/api/prisma/migrations/20240202093215_api/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE `agenda` ADD COLUMN `isNamed` BOOLEAN NOT NULL DEFAULT false, + ADD COLUMN `isPublic` BOOLEAN NOT NULL DEFAULT true; diff --git a/packages/api/prisma/schema.prisma b/packages/api/prisma/schema.prisma index df9cec09..18600fb4 100644 --- a/packages/api/prisma/schema.prisma +++ b/packages/api/prisma/schema.prisma @@ -13,6 +13,8 @@ model Agenda { title String resolution String content String + isNamed Boolean @default(false) + isPublic Boolean @default(true) startAt DateTime? @map("start_at") endAt DateTime? @map("end_at") createdAt DateTime @default(now()) @map("created_at") @@ -24,6 +26,7 @@ model Agenda { @@map("agenda") } + model User { id Int @id @default(autoincrement()) username String @unique @@ -122,4 +125,4 @@ enum ChatType { notice @@map("chat_type") -} +} \ No newline at end of file diff --git a/packages/api/src/service/admin.agenda.ts b/packages/api/src/service/admin.agenda.ts index 75d5993a..d5753243 100644 --- a/packages/api/src/service/admin.agenda.ts +++ b/packages/api/src/service/admin.agenda.ts @@ -32,10 +32,18 @@ const selectAgendaDefaultFields = { }, }; +const selectAgendaTypeFields = { + select: { + isNamed: true, + isPublic: true, + }, +}; + export const createAgenda = async ({ title, resolution, content, + type, choices, voters, }: schema.AdminAgendaCreate) => { @@ -43,6 +51,8 @@ export const createAgenda = async ({ title, resolution, content, + isNamed: type.named, + isPublic: type.public, choices: { create: choices.map(name => ({ name })), }, @@ -59,6 +69,7 @@ export const createAgenda = async ({ data: createAgendaQuery, select: { ...selectAgendaDefaultFields.select, + ...selectAgendaTypeFields.select, choices: true, voters: selectOnlyUser, }, @@ -66,6 +77,10 @@ export const createAgenda = async ({ const agendaVotable: PreparingAgenda = { ...createdAgenda, + type: { + named: createdAgenda.isNamed, + public: createdAgenda.isPublic, + }, status: "preparing", choices: createdChoices, voters: { @@ -119,6 +134,7 @@ export const startAgenda = async (agendaId: number, user: User) => { }, select: { ...selectAgendaDefaultFields.select, + ...selectAgendaTypeFields.select, choices: { include: { users: true, @@ -133,6 +149,10 @@ export const startAgenda = async (agendaId: number, user: User) => { const ongoingAgenda: OngoingAgenda = { ...updatedAgenda, status: "ongoing", + type: { + named: updatedAgenda.isNamed, + public: updatedAgenda.isPublic, + }, voters: { voted: 0, total: updatedVoters.length, @@ -166,6 +186,7 @@ export const terminateAgenda = async (agendaId: number, user: User) => { }, select: { ...selectAgendaDefaultFields.select, + ...selectAgendaTypeFields.select, choices: { include: { users: true, @@ -195,6 +216,10 @@ export const terminateAgenda = async (agendaId: number, user: User) => { // eslint-disable-next-line no-underscore-dangle count: choice._count.users, })), + type: { + named: updatedAgenda.isNamed, + public: updatedAgenda.isPublic, + }, voters: { voted: updatedChoices.reduce( (acc, choice) => acc + choice.users.length, @@ -248,6 +273,8 @@ export const updateAgenda = async (agendaUpdate: schema.AdminAgendaUpdate) => { data: agendaUpdate.choices.map(it => ({ name: it })), }, }, + isNamed: agendaUpdate.type.named, + isPublic: agendaUpdate.type.public, voters: { createMany: { data: agendaUpdate.voters.total.map(it => ({ @@ -258,6 +285,7 @@ export const updateAgenda = async (agendaUpdate: schema.AdminAgendaUpdate) => { }, select: { ...selectAgendaDefaultFields.select, + ...selectAgendaTypeFields.select, choices: true, voters: selectOnlyUser, }, @@ -278,6 +306,10 @@ export const updateAgenda = async (agendaUpdate: schema.AdminAgendaUpdate) => { id: choice.id, name: choice.name, })), + type: { + named: updatedAgenda.isNamed, + public: updatedAgenda.isPublic, + }, voters: { voted: 0, total: voters.length, @@ -302,6 +334,10 @@ export const updateAgenda = async (agendaUpdate: schema.AdminAgendaUpdate) => { name: choice.name, count: 0, })), + type: { + named: updatedAgenda.isNamed, + public: updatedAgenda.isPublic, + }, voters: { voted: [], total: voters.map(voter => voter.user), @@ -349,6 +385,7 @@ export const retrieveAll = async (): Promise => { where: { deletedAt: null }, select: { ...selectAgendaDefaultFields.select, + ...selectAgendaTypeFields.select, startAt: true, endAt: true, deletedAt: true, @@ -380,6 +417,11 @@ export const retrieveAll = async (): Promise => { content: agenda.content, resolution: agenda.resolution, status, + // TODO: remove workaround + type: { + named: agenda.isNamed, + public: agenda.isPublic, + }, choices: agenda.choices.map(choice => ({ id: choice.id, name: choice.name, diff --git a/packages/api/src/service/agenda.ts b/packages/api/src/service/agenda.ts index 1a7dddfa..323614ed 100644 --- a/packages/api/src/service/agenda.ts +++ b/packages/api/src/service/agenda.ts @@ -15,7 +15,17 @@ export const retrieveAll = async ( select: { id: true, name: true, - users: true, + users: { + select: { + userId: true, + choiceId: true, + user: { + select: { + displayName: true, + }, + }, + }, + }, }, }, }, @@ -35,11 +45,23 @@ export const retrieveAll = async ( title: agenda.title, content: agenda.content, resolution: agenda.resolution, + type: { named: agenda.isNamed, public: agenda.isPublic }, voters: { - voted: agenda.choices.reduce( - (acc, choice) => acc + choice.users.length, - 0, - ), + voted: agenda.isNamed + ? agenda.choices.reduce( + (acc, choice) => [ + ...acc, + ...choice.users.map(u => ({ + displayName: u.user.displayName, + choiceId: u.choiceId, + })), + ], + [] as { displayName: string; choiceId: number }[], + ) + : agenda.choices.reduce( + (acc, choice) => acc + choice.users.length, + 0, + ), total: agenda.voters.length, }, endAt: agenda.endAt, diff --git a/packages/interface/src/admin/agenda/common.ts b/packages/interface/src/admin/agenda/common.ts index 6f4b480a..bd98beff 100644 --- a/packages/interface/src/admin/agenda/common.ts +++ b/packages/interface/src/admin/agenda/common.ts @@ -7,22 +7,19 @@ import { User } from "@/user"; * AdminAgendaStatus * some description about admin agenda status type goes here */ -export const AdminAgendaStatus = z.enum([...AgendaStatus.options, "preparing"]); +export const AdminAgendaStatus = z.enum(AgendaStatus.options); export type AdminAgendaStatus = z.infer; /** * AdminAgenda * some description about admin agenda schema goes here */ -export const AdminAgenda = AgendaBase.omit({ - voters: true, - status: true, -}).extend({ +export const AdminAgenda = AgendaBase.extend({ + status: AdminAgendaStatus, voters: z.object({ voted: z.array(User), total: z.array(User), }), - status: AdminAgendaStatus, choices: z.array(ChoiceWithResult), endAt: z.string(), // currently used only on terminated admin agendas }); @@ -36,6 +33,10 @@ export const AdminAgendaCreate = z.object({ title: z.string().min(1).max(255), content: z.string().min(1).max(255), resolution: z.string().min(1).max(255), + type: z.object({ + named: z.boolean(), + public: z.boolean(), + }), choices: z.array(z.string().min(1).max(255)).min(1), voters: z.object({ total: z.array(z.number()), diff --git a/packages/interface/src/agenda/common.ts b/packages/interface/src/agenda/common.ts index 0587b2aa..eefb4f61 100644 --- a/packages/interface/src/agenda/common.ts +++ b/packages/interface/src/agenda/common.ts @@ -29,9 +29,22 @@ export const AgendaBase = z.object({ title: z.string(), content: z.string(), resolution: z.string(), + type: z.object({ + named: z.boolean(), + public: z.boolean(), + }), status: z.never(), // Must be overridden voters: z.object({ - voted: z.number(), + voted: z.union([ + z.number(), + z.array( + z.object({ + // userId: z.number(), + displayName: z.string(), + choiceId: z.number(), + }), + ), + ]), total: z.number(), }), }); diff --git a/packages/web/src/components/atoms/Toggle.tsx b/packages/web/src/components/atoms/Toggle.tsx new file mode 100644 index 00000000..a548c515 --- /dev/null +++ b/packages/web/src/components/atoms/Toggle.tsx @@ -0,0 +1,60 @@ +import styled from "@emotion/styled"; +import { css } from "@emotion/react"; + +type Size = number | "hug" | "fill"; +type Position = "left" | "middle" | "right"; + +const calcSize = (size: Size) => { + if (size === "fill") return "fill"; + if (size === "hug") return "fit-content"; + return `${size}px`; +}; +const calcBorderRadius = (position: Position) => { + if (position === "left") return "5px 0px 0px 5px"; + if (position === "middle") return "0px 0px 0px 0px"; + if (position === "right") return "0px 5px 5px 0px"; + return "0px 0px 0px 0px"; +}; + +export const ToggleContainor = styled.div<{ + w?: Size; + h?: Size; +}>( + ({ w = "fill", h = 20 }) => css` + display: flex; + width: ${calcSize(w)}; + height: ${calcSize(h)}; + border: none; + justify-content: center; + align-items: center; + overflow: hidden; + `, +); + +export const ToggleButton = styled.div<{ + selected: boolean; + position: Position; +}>( + ({ selected, position, theme }) => css` + display: flex; + width: fill; + height: 100%; + border-style: solid; + border-width: 1px; + border-radius: ${calcBorderRadius(position)}; + border-color: ${selected ? theme.colors.blue500 : theme.colors.gray300}; + border-left-width: ${position === "left" || selected ? "1px" : "0px"}; + border-right-width: ${position === "right" || selected ? "1px" : "0px"}; + justify-content: center; + align-items: center; + padding: 4px 5px 4px 5px; + background-color: ${selected ? theme.colors.blue200 : theme.colors.white}; + transition-duration: 0.25s; + transition-property: background-color; + + &:hover { + cursor: ${selected ? "default" : "pointer"}; + background-color: ${theme.colors.blue200}; + } + `, +); diff --git a/packages/web/src/components/atoms/index.ts b/packages/web/src/components/atoms/index.ts index a4ac980c..e75cfdec 100644 --- a/packages/web/src/components/atoms/index.ts +++ b/packages/web/src/components/atoms/index.ts @@ -21,3 +21,4 @@ export * from "./TaggersBox"; export * from "./HyperText"; export * from "./PresetOption"; export * from "./TagSelect"; +export * from "./Toggle"; diff --git a/packages/web/src/components/molecules/AdminAgendaTags.tsx b/packages/web/src/components/molecules/AdminAgendaTags.tsx index c8f3707b..a27a01db 100644 --- a/packages/web/src/components/molecules/AdminAgendaTags.tsx +++ b/packages/web/src/components/molecules/AdminAgendaTags.tsx @@ -1,108 +1,129 @@ -import { DownArrowIcon } from "@biseo/web/assets"; -import { BorderedBox, Box, Text } from "@biseo/web/components/atoms"; +import React from "react"; +import { + Box, + Text, + ToggleContainor, + ToggleButton, +} from "@biseo/web/components/atoms"; -export const AdminAgendaTags: React.FC = () => ( +interface SelectProps { + switchPublic: (prev: boolean) => void; + switchNamed: (prev: boolean) => void; + ispublic: boolean; + isnamed: boolean; +} + +interface TagProps { + ispublic: boolean; + isnamed: boolean; +} + +export const AdminAgendaTags: React.FC = ({ + ispublic = true, + isnamed = false, +}) => ( - + 투표 결과 - - - 비공개 - - + + + + 공개 + + + + + 비공개 + + + - + 투표 상세 - - - 무기명 - - + + + + 기명 + + + + + 무기명 + + + ); -export const AdminAgendaTagsSelect: React.FC = () => ( +export const AdminAgendaTagsSelect: React.FC = ({ + switchPublic, + switchNamed, + ispublic, + isnamed, +}) => ( 투표 결과 - - - 비공개 - - - - - - + + { + switchPublic(true); + }} + > + + 공개 + + + { + switchPublic(false); + }} + > + + 비공개 + + + 투표 상세 - - - 무기명 - - - - - - + + { + switchNamed(true); + }} + > + + 기명 + + + { + switchNamed(false); + }} + > + + 무기명 + + + ); diff --git a/packages/web/src/components/molecules/AgendaCard/AdminOngoingAgendaCard.tsx b/packages/web/src/components/molecules/AgendaCard/AdminOngoingAgendaCard.tsx index 2c76ab1e..29751137 100644 --- a/packages/web/src/components/molecules/AgendaCard/AdminOngoingAgendaCard.tsx +++ b/packages/web/src/components/molecules/AgendaCard/AdminOngoingAgendaCard.tsx @@ -15,12 +15,6 @@ import { useAdminAgenda } from "@biseo/web/services/admin-agenda"; import { row, center, justify, gap, text, w, column } from "@biseo/web/styles"; -const agendaTags = { - public: true, - identified: false, - votable: true, -}; - interface Props { agenda: AdminAgenda; } @@ -45,7 +39,14 @@ export const AdminOngoingAgendaCard: React.FC = ({ agenda }) => { return (
- +

{agenda.title}

{agenda.content}

diff --git a/packages/web/src/components/molecules/AgendaCard/AdminPreparingAgendaCard.tsx b/packages/web/src/components/molecules/AgendaCard/AdminPreparingAgendaCard.tsx index 24131033..f06959bc 100644 --- a/packages/web/src/components/molecules/AgendaCard/AdminPreparingAgendaCard.tsx +++ b/packages/web/src/components/molecules/AgendaCard/AdminPreparingAgendaCard.tsx @@ -10,12 +10,6 @@ import { useAdminAgenda } from "@biseo/web/services/admin-agenda"; import { column, gap, text, w } from "@biseo/web/styles"; -const agendaTags = { - public: true, - identified: false, - votable: true, -}; - interface Props { agenda: AdminAgenda; } @@ -44,7 +38,7 @@ export const AdminPreparingAgendaCard: React.FC = ({ agenda }) => { const startVote = (e: React.MouseEvent) => { if (!validated) { - alert("투표 대상을 설정해주세요"); + alert("투표 대상을 설정해주세요"); // eslint-disable-line no-alert // TODO: button 아래 card click으로 간주되어 edit modal로의 redirection 때문에 alert가 뜨지 않음 return; } @@ -55,7 +49,14 @@ export const AdminPreparingAgendaCard: React.FC = ({ agenda }) => { return (
- +

{agenda.title}

{agenda.content}

diff --git a/packages/web/src/components/molecules/AgendaCard/AdminTerminatedAgendaCard.tsx b/packages/web/src/components/molecules/AgendaCard/AdminTerminatedAgendaCard.tsx index 009c176f..2cecd9a0 100644 --- a/packages/web/src/components/molecules/AgendaCard/AdminTerminatedAgendaCard.tsx +++ b/packages/web/src/components/molecules/AgendaCard/AdminTerminatedAgendaCard.tsx @@ -9,12 +9,6 @@ import { AgendaTag } from "@biseo/web/components/molecules/AgendaTag"; import { align, column, gap, justify, row, text, w } from "@biseo/web/styles"; import { formatDateSimple } from "@biseo/web/utils/format"; -const agendaTags = { - public: true, - identified: false, - votable: false, -}; - interface Props { agenda: AdminAgenda; } @@ -29,9 +23,9 @@ export const AdminTerminatedAgendaCard: React.FC = ({ agenda }) => {

diff --git a/packages/web/src/components/molecules/AgendaCard/OngoingAgendaCard.tsx b/packages/web/src/components/molecules/AgendaCard/OngoingAgendaCard.tsx index db257052..53432bb3 100644 --- a/packages/web/src/components/molecules/AgendaCard/OngoingAgendaCard.tsx +++ b/packages/web/src/components/molecules/AgendaCard/OngoingAgendaCard.tsx @@ -18,12 +18,6 @@ interface OngoingAgendaProps { agenda: OngoingAgenda; } -const agendaTags = { - public: true, - identified: false, - votable: true, -}; - export const OngoingAgendaCard: React.FC = ({ agenda }) => { const [chosenChoiceId, setChosenChoiceId] = useState(0); const { voteAgenda } = useAgenda(state => ({ @@ -75,8 +69,8 @@ export const OngoingAgendaCard: React.FC = ({ agenda }) => {

diff --git a/packages/web/src/components/molecules/AgendaCard/PreparingAgendaCard.tsx b/packages/web/src/components/molecules/AgendaCard/PreparingAgendaCard.tsx index 2f7616f7..924e1c95 100644 --- a/packages/web/src/components/molecules/AgendaCard/PreparingAgendaCard.tsx +++ b/packages/web/src/components/molecules/AgendaCard/PreparingAgendaCard.tsx @@ -7,12 +7,6 @@ import { AgendaTag } from "@biseo/web/components/molecules/AgendaTag"; import { column, gap, text } from "@biseo/web/styles"; -const agendaTags = { - public: true, - identified: false, - votable: true, -}; - interface Props { agenda: PreparingAgenda; } @@ -22,8 +16,8 @@ export const PreparingAgendaCard: React.FC = ({ agenda }) => (
diff --git a/packages/web/src/components/molecules/AgendaCard/TerminatedAgendaCard.tsx b/packages/web/src/components/molecules/AgendaCard/TerminatedAgendaCard.tsx index f23369ba..984ad1be 100644 --- a/packages/web/src/components/molecules/AgendaCard/TerminatedAgendaCard.tsx +++ b/packages/web/src/components/molecules/AgendaCard/TerminatedAgendaCard.tsx @@ -1,4 +1,4 @@ -import React, { useState, useMemo } from "react"; +import React, { useState, useMemo, useCallback, useRef } from "react"; import type { TerminatedAgenda } from "@biseo/interface/agenda"; @@ -7,6 +7,7 @@ import { AgendaTag } from "@biseo/web/components/molecules/AgendaTag"; import { OptionVoteResult } from "@biseo/web/components/molecules/OptionVoteResult"; import { VoteResult } from "@biseo/web/components/molecules/VoteResult"; import { VoteDetail } from "@biseo/web/components/molecules/VoteDetail"; +import { VotedMembers } from "@biseo/web/components/molecules/VotedMembers"; import { VoteParticipate } from "@biseo/web/components/molecules/VoteParticipate"; import { align, @@ -24,19 +25,22 @@ import { formatTime, } from "@biseo/web/utils/format"; -const agendaTags = { - public: true, - identified: false, - votable: true, -}; - interface Props { agenda: TerminatedAgenda; } +type Voter = { + displayName: string; + choiceId: number; +}; + export const TerminatedAgendaCard: React.FC = ({ agenda }) => { const [enabled, setEnabled] = useState(false); - const [revealChoice, setRevealChoice] = useState(false); + // const [isDragging, setIsDragging] = useRef(false); + const isDragging = useRef(false); + const [revealChoice, setRevealChoice] = useState(agenda.type.named); + const [detectDrag, setDetectDrag] = useState(); + const switchRevealChoice = (prev: boolean) => { setRevealChoice(!prev); }; @@ -44,12 +48,54 @@ export const TerminatedAgendaCard: React.FC = ({ agenda }) => { () => agenda.choices.reduce((acc, c) => acc + c.count, 0), [agenda.choices], ); + const checkDrag = useCallback(() => { + if (!isDragging.current) { + setEnabled(value => !value); + clearTimeout(detectDrag); + } + window.removeEventListener("mouseup", checkDrag); + }, []); + + const optionVoteResult = useCallback(() => { + if (agenda.type.public) { + return agenda.choices.map(choice => ( + + )); + } + let currmax = 0; + return agenda.choices.map(choice => { + const ismax = choice.count >= currmax; + currmax = ismax ? choice.count : currmax; + return ( + + ); + }); + }, [revealChoice]); + return ( { - setEnabled(value => !value); + onMouseDown={e => { + isDragging.current = false; + window.addEventListener("mouseup", checkDrag); + setDetectDrag( + setTimeout(() => { + isDragging.current = true; + }, 200), + ); e.stopPropagation(); }} > @@ -71,35 +117,44 @@ export const TerminatedAgendaCard: React.FC = ({ agenda }) => {
-
- {agenda.choices.map(choice => ( - - ))} -
+
{optionVoteResult()}
- + + {agenda.type.named ? ( +
+ {agenda.choices.map(choice => ( + ) + .filter(voter => { + if (choice.id === voter.choiceId) { + return true; + } + return false; + }) + .map(voter => voter.displayName)} + name={choice.name} + /> + ))} +
+ ) : null}
) : (
diff --git a/packages/web/src/components/molecules/OptionVoteResult.tsx b/packages/web/src/components/molecules/OptionVoteResult.tsx index 36b6cfca..661c8c50 100644 --- a/packages/web/src/components/molecules/OptionVoteResult.tsx +++ b/packages/web/src/components/molecules/OptionVoteResult.tsx @@ -4,6 +4,7 @@ import { Box, Text } from "@biseo/web/components/atoms"; import type { Color } from "@biseo/web/theme"; interface Props { + ispublic: boolean; name: string; count: number; totalCount: number; @@ -29,6 +30,7 @@ const Background = styled.div<{ `; export const OptionVoteResult: React.FC = ({ + ispublic, name, count, totalCount, @@ -53,7 +55,7 @@ export const OptionVoteResult: React.FC = ({ {name} - {count} + {ispublic && count} diff --git a/packages/web/src/components/molecules/VoteDetail.tsx b/packages/web/src/components/molecules/VoteDetail.tsx index 4d6e6f27..e490ae14 100644 --- a/packages/web/src/components/molecules/VoteDetail.tsx +++ b/packages/web/src/components/molecules/VoteDetail.tsx @@ -2,20 +2,14 @@ import React from "react"; import { Box, Text, Tag } from "@biseo/web/components/atoms"; interface Props { - type: boolean; + named: boolean; } -export const VoteDetail: React.FC = ({ type }) => ( - <> - {type ? ( - <>TODO - ) : ( - - - 투표 상세 - - - - )} - +export const VoteDetail: React.FC = ({ named }) => ( + + + 투표 상세 + + + ); diff --git a/packages/web/src/components/molecules/VoteParticipate.tsx b/packages/web/src/components/molecules/VoteParticipate.tsx index 198c3de3..94b731b3 100644 --- a/packages/web/src/components/molecules/VoteParticipate.tsx +++ b/packages/web/src/components/molecules/VoteParticipate.tsx @@ -1,18 +1,25 @@ import React, { useMemo, useState } from "react"; import { Box, Text, Tag } from "@biseo/web/components/atoms"; +type Voter = { + displayName: string; + choiceId: number; +}; + interface Props { - voted: number; + named: boolean; + voted: number | Voter[]; total: number; } -export const VoteParticipate: React.FC = ({ voted, total }) => { +export const VoteParticipate: React.FC = ({ named, voted, total }) => { + const votedLength = named ? (voted as Array).length : voted; const [hover, setHover] = useState(false); const participantInfo = useMemo( () => hover - ? `투표 참여자 ${voted}명 / 투표 대상자 ${total}명` - : `${voted}/${total}`, + ? `투표 참여자 ${votedLength}명 /투표 대상자 ${total}명` + : `${votedLength}/${total}`, [hover], ); diff --git a/packages/web/src/components/molecules/VotedMembers.tsx b/packages/web/src/components/molecules/VotedMembers.tsx new file mode 100644 index 00000000..607dc795 --- /dev/null +++ b/packages/web/src/components/molecules/VotedMembers.tsx @@ -0,0 +1,43 @@ +import React, { useCallback } from "react"; +import { Box } from "@biseo/web/components/atoms"; +import { border, h, w, round, text } from "@biseo/web/styles"; + +interface Props { + name: string; + userList: (string | undefined)[]; +} + +export const VotedMembers: React.FC = ({ name, userList }) => { + const memberString = useCallback(() => { + if (userList.length === 0) { + return "-"; + } + return userList.sort().reduce((prev, curr) => `${prev} ${curr}`); + }, [userList]); + + return ( + +
+ +
+
{name}
+
+ +
+
+ {memberString()} +
+
+
+
+
+ ); +}; diff --git a/packages/web/src/components/organisms/AgendaSection.tsx b/packages/web/src/components/organisms/AgendaSection.tsx index f32db6e9..098cf3ac 100644 --- a/packages/web/src/components/organisms/AgendaSection.tsx +++ b/packages/web/src/components/organisms/AgendaSection.tsx @@ -11,6 +11,8 @@ import { import { scroll } from "@biseo/web/styles"; import { css } from "@emotion/react"; +// for test + const gridLayout = css` display: grid; grid-template-columns: 380px 300px; @@ -52,8 +54,9 @@ export const AgendaSection: React.FC = () => { const getAgendas = useCallback( (agendaStatus: AgendaStatus) => { if (agendaStatus === "preparing") return preparingAgendas; - if (agendaStatus === "ongoing") - return ongoingAgendas.sort((a, b) => a.voters.voted - b.voters.voted); + if (agendaStatus === "ongoing") { + return ongoingAgendas.sort((a, b) => +a.voters.voted - +b.voters.voted); + } if (agendaStatus === "terminated") { const recent24Hours = new Date(); diff --git a/packages/web/src/components/organisms/CreateAgendaModal.tsx b/packages/web/src/components/organisms/CreateAgendaModal.tsx index daedf644..7ab0dee5 100644 --- a/packages/web/src/components/organisms/CreateAgendaModal.tsx +++ b/packages/web/src/components/organisms/CreateAgendaModal.tsx @@ -32,6 +32,8 @@ export const CreateAgendaModal: React.FC = () => { const [title, setTitle] = useState(""); const [content, setContent] = useState(""); + const [isnamed, setIsnamed] = useState(false); + const [ispublic, setIspublic] = useState(true); const [resolution, setResolution] = useState(""); const [choices, setChoices] = useState([]); const [voters, setVoters] = useState([]); @@ -44,6 +46,12 @@ export const CreateAgendaModal: React.FC = () => { const onChangeResolution = (e: React.ChangeEvent) => { setResolution(e.target.value); }; + const onChangeIspublic = (e: boolean) => { + setIspublic(e); + }; + const onChangeIsnamed = (e: boolean) => { + setIsnamed(e); + }; const [template, setTemplate] = useState(0); const applyTemplate = (templateId: number) => { @@ -100,6 +108,10 @@ export const CreateAgendaModal: React.FC = () => { const onSubmit = () => { if (!validated) return; createAgenda({ + type: { + named: isnamed, + public: ispublic, + }, title, content, resolution, @@ -190,7 +202,12 @@ export const CreateAgendaModal: React.FC = () => { bg="blue100" > - + { const [title, setTitle] = useState(targetAgenda?.title || ""); const [content, setContent] = useState(targetAgenda?.content || ""); + const [isNamed, setIsnamed] = useState(targetAgenda?.type.named || Boolean); + const [isPublic, setIspublic] = useState( + targetAgenda?.type.public || Boolean, + ); const [resolution, setResolution] = useState(targetAgenda?.resolution || ""); const [template, setTemplate] = useState(0); const [choices, setChoices] = useState( @@ -53,12 +57,18 @@ export const EditAgendaModal: React.FC = () => { const onChangeTitle = (e: React.ChangeEvent) => { setTitle(e.target.value); }; - const onChangeContent = (e: React.ChangeEvent) => { + const onChangeContent = (e: React.ChangeEvent) => { setContent(e.target.value); }; const onChangeResolution = (e: React.ChangeEvent) => { setResolution(e.target.value); }; + const onChangeIspublic = (e: boolean) => { + setIspublic(e); + }; + const onChangeIsnamed = (e: boolean) => { + setIsnamed(e); + }; const [newchoice, setNewchoice] = useState(""); const onChangeChoice = (e: React.ChangeEvent) => { @@ -119,6 +129,7 @@ export const EditAgendaModal: React.FC = () => { title, content, resolution, + type: { named: isNamed, public: isPublic }, voters: { total: voters, }, @@ -150,10 +161,7 @@ export const EditAgendaModal: React.FC = () => { - + { padHorizontal={15} round={5} > - + { } }; + const isPublic = + targetAgenda?.type.public === undefined ? false : targetAgenda?.type.public; + const isNamed = + targetAgenda?.type.named === undefined ? false : targetAgenda?.type.named; + return ( @@ -77,7 +82,7 @@ export const OngoingAgendaModal: React.FC = () => { padHorizontal={15} round={5} > - +