Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions src/client/Layout.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import { Box, CssBaseline, Link, Sheet, Typography } from "@mui/joy";
import React from "react";
import { Box, Button, CssBaseline, Link, Sheet, Typography } from "@mui/joy";
import { Toaster } from "sonner";
import { GitHub } from "@mui/icons-material"
import hyLogo from "./assets/hy_logo.svg"
import toskaLogo from "./assets/toska13.png"
import { Link as RouterLink, Outlet } from "react-router-dom";
import { useTranslation } from "react-i18next";
import { FeedbackProvider, useFeedback } from "./feedback/FeedbackProvider";

const Header = () => {
const { t } = useTranslation()
const { mode, setMode } = useFeedback()

return (
<Sheet sx={{
Expand All @@ -28,9 +29,13 @@ const Header = () => {
</Box>
</RouterLink>
<Typography level="body2" sx={{ userSelect: "none" }}>{t("navbar.description")}</Typography>
<Box ml="auto">
<Button variant={mode === "disabled" ? "plain" : "solid"} onClick={() => setMode(mode === "disabled" ? "edit" : "disabled")}>Palautetila</Button>
</Box>
</Sheet>
)
}

const Footer = () => (
<Sheet sx={{
mt: "auto",
Expand All @@ -55,11 +60,13 @@ const Footer = () => (
const Layout = () => (
<CssBaseline>
<Toaster />
<Box display="flex" flexDirection="column" minHeight="100vh">
<Header />
<Outlet />
<Footer />
</Box>
<FeedbackProvider>
<Box display="flex" flexDirection="column" minHeight="100vh">
<Header />
<Outlet />
<Footer />
</Box>
</FeedbackProvider>
</CssBaseline>
)

Expand Down
5 changes: 3 additions & 2 deletions src/client/components/Calculator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import useContractStore, { useTotalHours, useWorkHourCalculatorFields } from '..
import { Option } from '../types'
import { courseTypeOptions, creditOptions, preparationHoursTableData, studentCountOptions } from '../calculatorConfig'
import { SectionDivider } from './common'
import FeedbackTargetContainer from '../feedback/FeedbackTargetContainer'

const HoursChip = ({ hours }: { hours: number }) => (
<Chip variant="soft">{`${hours} tuntia`}</Chip>
Expand All @@ -16,7 +17,7 @@ const SalaryChip = ({ salary, unit='€/h' }: { salary: number, unit?: string })


const InputContainer = ({ children, resultName, resultChip, infoBox, sx }: { children: React.ReactNode, resultName?: string, resultChip?: React.ReactNode, infoBox?: React.ReactNode, sx?: SxProps }) => (
<Box display="flex" flexDirection="column" alignItems="stretch" sx={sx} >
<FeedbackTargetContainer feedbackId="asd" display="flex" flexDirection="column" alignItems="stretch" sx={sx} >
<Sheet sx={{
flexGrow: 1,
display: "flex",
Expand All @@ -41,7 +42,7 @@ const InputContainer = ({ children, resultName, resultChip, infoBox, sx }: { chi
}

</Sheet>
</Box>
</FeedbackTargetContainer>
)


Expand Down
23 changes: 23 additions & 0 deletions src/client/feedback/FeedbackForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Box, Button, FormControl, FormLabel, Input, Sheet, Textarea, Typography } from "@mui/joy"
import React from "react"

const FeedbackForm = () => {
const [feedbackText, setFeedbackText] = React.useState("")

return (
<Sheet sx={{ resize: "horizontal" }}>
<Box p="0.5rem">
<form>
<FormControl required>
<FormLabel>Palaute</FormLabel>
<Textarea slotProps={{ textarea: { minLength: 5 } }} value={feedbackText} onChange={(e) => setFeedbackText(e.target.value)} />
</FormControl>
<Button size="sm" sx={{ my: "0.5rem" }} disabled={feedbackText.length < 5}>Lähetä</Button>
<Typography level="body3">Huom., annat palautetta omalla nimelläsi</Typography>
</form>
</Box>
</Sheet>
)
}

export default FeedbackForm
26 changes: 26 additions & 0 deletions src/client/feedback/FeedbackProvider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import React from "react";

type Mode = "disabled"|"edit"|"view"

const FeedbackContext = React.createContext<{
mode: Mode,
setMode: (newMode: Mode) => void
}>({
mode: "disabled",
setMode: (mode: Mode) => {}
})

export const useFeedback = () => React.useContext(FeedbackContext)

export const FeedbackProvider = ({ children }: { children: React.ReactNode }) => {
const [mode, setMode] = React.useState<Mode>("edit")

return (
<FeedbackContext.Provider value={{
mode,
setMode: setMode
}}>
{children}
</FeedbackContext.Provider>
)
}
64 changes: 64 additions & 0 deletions src/client/feedback/FeedbackTargetContainer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import React from "react";
import { useFeedback } from "./FeedbackProvider";
import { Box, Tooltip } from "@mui/joy";
import { SxProps } from "@mui/joy/styles/types";
import FeedbackForm from "./FeedbackForm";

type FeedbackTargetContainerProps = {
feedbackId: string
} & React.ComponentProps<typeof Box>

const ActiveFeedbackTargetContainer = (props: FeedbackTargetContainerProps) => {
const [open, setOpen] = React.useState(false)
const [opened, setOpened] = React.useState(false)

const activeSx: SxProps = {
outlineStyle: "solid",
outlineColor: "lightblue",
outlineWidth: "2px",
outlineOffset: "2px",
borderRadius: "2px",
cursor: "pointer",
"&:hover": {
outlineColor: "blue",
},
}

const handleClick = () => {
const newOpen = !open
setOpen(newOpen)
if (newOpen) setOpened(true)
console.log(`Feedback ${newOpen ? "opened" : "closed"} for `, props.feedbackId)
}

return (
<Tooltip variant="outlined" arrow title={<FeedbackForm />} open={open} keepMounted={opened}>
<Box {...props} sx={{
...activeSx,
...props.sx
}} onClick={handleClick}>
{props.children}
</Box>
</Tooltip>
)
}

const FeedbackTargetContainer = (props: FeedbackTargetContainerProps) => {
const { mode } = useFeedback()

if (mode === "disabled") {
return (
<Box {...props}>
{props.children}
</Box>
)
}

return (
<ActiveFeedbackTargetContainer {...props}>
{props.children}
</ActiveFeedbackTargetContainer>
)
}

export default FeedbackTargetContainer