Skip to content

Commit

Permalink
Update admin-site to support json schema
Browse files Browse the repository at this point in the history
  • Loading branch information
norbye committed Jul 24, 2023
1 parent 2f30739 commit d434e2e
Show file tree
Hide file tree
Showing 15 changed files with 400 additions and 124 deletions.
18 changes: 15 additions & 3 deletions frontend/src/components/Application/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,30 @@ import ReadMore from "src/components/ReadMore";
import Wrapper from "./Wrapper";
import GroupName from "./GroupName";
import DeleteApplication from "./DeleteApplication";
import { JsonFieldInput } from "src/types";
import { filterEditableFields } from "src/utils/jsonFieldHelper";

interface ApplicationProps {
text: string;
questions: JsonFieldInput[];
responses: Record<string, string>;
applicationId: number;
}

const Application: React.FC<ApplicationProps> = ({ text, applicationId }) => {
const Application: React.FC<ApplicationProps> = ({
questions,
responses,
applicationId,
}) => {
return (
<div>
<GroupName>Søknad</GroupName>
<Wrapper>
<ReadMore truncateLength={400} text={text} />
<ReadMore
truncateLength={400}
text={filterEditableFields(questions)
.map((question) => question.name + ":\n" + responses[question.id])
.join("\n\n")}
/>
</Wrapper>
<DeleteApplication applicationId={applicationId} />
</div>
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/InputValidationFeedback/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from "react";
import "./styles.css";

interface InputValidationFeedbackProps {
error: string;
error?: string;
}

const InputValidationFeedback: React.FC<InputValidationFeedbackProps> = ({
Expand Down
25 changes: 25 additions & 0 deletions frontend/src/components/JsonFieldEditor/PhoneInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import { Field } from "formik";
import React from "react";
import { JsonFieldPhoneInput } from "src/types";
import { StyledField } from "../styledFields";

type PhoneInputProps = {
field: JsonFieldPhoneInput;
index: number;
};

const PhoneInput: React.FC<PhoneInputProps> = ({ field, index }) => {
return (
<>
<p>Telefonnummer</p>
<StyledField
name={"questions." + index + ".name"}
placeholder={""}
label={"Label"}
/>
<StyledField name={"questions." + index + ".label"} label={"Label"} />
</>
);
};

export default PhoneInput;
24 changes: 24 additions & 0 deletions frontend/src/components/JsonFieldEditor/Text.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Field } from "formik";
import React from "react";
import { JsonFieldText } from "src/types";
import TextAreaField from "src/components/TextAreaField";

type TextProps = {
field: JsonFieldText;
index: number;
};

const Text: React.FC<TextProps> = ({ field, index }) => {
return (
<>
<p>Informasjonstekst</p>
<Field
name={"questions." + index + ".text"}
component={TextAreaField}
placeholder={""}
/>
</>
);
};

export default Text;
30 changes: 30 additions & 0 deletions frontend/src/components/JsonFieldEditor/TextArea.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { Field } from "formik";
import React from "react";
import { JsonFieldTextArea } from "src/types";
import { StyledField } from "../styledFields";
import TextAreaField from "../TextAreaField";

type TextAreaProps = {
field: JsonFieldTextArea;
index: number;
};

const TextArea: React.FC<TextAreaProps> = ({ field, index }) => {
return (
<>
<p>Langtekst-svar</p>
<StyledField
name={"questions." + index + ".name"}
placeholder={""}
label={"Label"}
/>
<Field
name={"questions." + index + ".label"}
component={TextAreaField}
placeholder={""}
/>
</>
);
};

export default TextArea;
28 changes: 28 additions & 0 deletions frontend/src/components/JsonFieldEditor/TextInput.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import React from "react";
import { JsonFieldTextInput } from "src/types";
import { StyledField } from "../styledFields";

type TextInputProps = {
field: JsonFieldTextInput;
index: number;
};

const TextInput: React.FC<TextInputProps> = ({ field, index }) => {
return (
<>
<p>Korttekst-svar</p>
<StyledField
name={"questions." + index + ".name"}
placeholder={""}
label={"Label"}
/>
<StyledField
name={"questions." + index + ".label"}
placeholder={""}
label={"Label"}
/>
</>
);
};

export default TextInput;
61 changes: 61 additions & 0 deletions frontend/src/components/JsonFieldEditor/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React, { useState } from "react";
import { Group, JsonFieldInput } from "src/types";
import styled from "styled-components";
import PhoneInput from "./PhoneInput";
import Text from "./Text";
import TextArea from "./TextArea";
import TextInput from "./TextInput";

type JsonFieldEditorProps = {
group: Group;
initialFields: JsonFieldInput[];
};

const JsonFieldEditor: React.FC<JsonFieldEditorProps> = ({
group,
initialFields,
}) => {
const [fields, setFields] = useState<JsonFieldInput[]>(initialFields);

return (
<EditorWrapper>
<h3>Rediger spørsmål for {group.name}</h3>
<FieldWrapper>
{fields.map((field, index) => {
if (field.type === "text")
return <Text key={index} field={field} index={index} />;
if (field.type === "textarea")
return <TextArea key={field.id} field={field} index={index} />;
if (field.type === "phoneinput")
return <PhoneInput key={field.id} field={field} index={index} />;
if (field.type === "textinput")
return <TextInput key={field.id} field={field} index={index} />;
return null;
})}
</FieldWrapper>
</EditorWrapper>
);
};

export default JsonFieldEditor;

const EditorWrapper = styled.div`
display: flex;
flex-direction: column;
gap: 0.2em;
width: 100%;
margin-bottom: 1em;
h3 {
margin: 0;
}
`;

const FieldWrapper = styled.div`
p {
margin: 0;
}
input {
display: block;
}
`;
14 changes: 10 additions & 4 deletions frontend/src/containers/AdmissionsContainer/Columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import FormatTime from "src/components/Time/FormatTime";
import { AdmissionsTableValues } from ".";
import { InnerTableValues } from "./InnerTable";
import DeleteApplication from "src/components/Application/DeleteApplication";
import { JsonFieldEditableInput } from "src/types";
import { filterEditableFields } from "src/utils/jsonFieldHelper";

const columnHelper = createColumnHelper<AdmissionsTableValues>();

Expand All @@ -29,9 +31,6 @@ export const columns = [
columnHelper.accessor("fullname", {
header: "Fullt navn",
}),
columnHelper.accessor("phoneNumber", {
header: "Tlf.",
}),
columnHelper.accessor("email", {
header: "E-post",
}),
Expand Down Expand Up @@ -81,9 +80,16 @@ export const innerColumns = [
header: "Gruppe",
size: 100,
}),
innerColumnHelper.accessor("text", {
innerColumnHelper.accessor("responses", {
header: "Søknadstekst",
size: 800,
cell: ({ row }) =>
filterEditableFields(row.original.groupQuestions).map((question) => (
<div key={question.id}>
<h3>{question.name}</h3>
<span>{row.original.responses[question.id]}</span>
</div>
)),
}),
innerColumnHelper.display({
id: "actions",
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/containers/AdmissionsContainer/InnerTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@ import {
} from "@tanstack/react-table";
import { innerColumns } from "./Columns";
import styled from "styled-components";
import { JsonFieldInput } from "src/types";

export interface InnerTableValues {
applicationId: number;
group: string;
text: string;
responses: Record<string, string>;
groupQuestions?: JsonFieldInput[];
}

interface AdmissionsInnerTableProps {
Expand Down
27 changes: 18 additions & 9 deletions frontend/src/containers/AdmissionsContainer/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,30 +13,32 @@ import { columns } from "./Columns";
import AdmissionsInnerTable, { InnerTableValues } from "./InnerTable";
import SubComponentWrapper from "./SubComponentWrapper";
import SubComponentHeader from "./SubComponentHeader";
import { Application } from "src/types";
import { Admission, Application, JsonFieldEditableInput } from "src/types";
import { useState } from "react";
import { TableWrapper } from "src/routes/AdminPageAbakusLeaderView/Wrapper";
import styled from "styled-components";
import Icon from "src/components/Icon";
import { filterEditableFields } from "src/utils/jsonFieldHelper";

interface AdmissionsContainerProps {
admission: Admission;
applications: Application[];
}

export interface AdmissionsTableValues {
username: string;
fullname: string;
phoneNumber: string;
email: string;
appliedWithinDeadline: boolean;
numApplications: number;
createdAt: string;
updatedAt: string;
text: string;
responses: Record<string, string>;
groupApplications: InnerTableValues[];
}

const AdmissionsContainer: React.FC<AdmissionsContainerProps> = ({
admission,
applications,
}) => {
const [expanded, setExpanded] = useState<ExpandedState>({});
Expand All @@ -47,18 +49,20 @@ const AdmissionsContainer: React.FC<AdmissionsContainerProps> = ({
id: application.pk,
username: application.user.username,
fullname: application.user.full_name,
phoneNumber: application.phone_number,
email: application.user.email,
appliedWithinDeadline: application.applied_within_deadline,
numApplications: application.group_applications.length,
createdAt: application.created_at,
updatedAt: application.updated_at,
text: application.text,
responses: application.responses,
groupApplications: application.group_applications.map(
(groupApplication) => ({
applicationId: application.pk,
group: groupApplication.group.name,
text: groupApplication.text,
groupQuestions: admission.groups.find(
(group) => group.pk === groupApplication.group.pk
)?.questions,
responses: groupApplication.responses,
})
),
})),
Expand All @@ -83,9 +87,14 @@ const AdmissionsContainer: React.FC<AdmissionsContainerProps> = ({
({ row }: { row: Row<AdmissionsTableValues> }) => (
<>
<SubComponentWrapper>
<SubComponentHeader>Prioriteringstekst</SubComponentHeader>
<p>{row.original.text}</p>
<SubComponentHeader>Søknader</SubComponentHeader>
{filterEditableFields(admission.questions).map((question) => {
return (
<div key={question.id}>
<h3>{question.name}</h3>
<span>{row.original.responses[question.id]}</span>
</div>
);
})}
<AdmissionsInnerTable
groupApplications={row.original.groupApplications}
/>
Expand Down

0 comments on commit d434e2e

Please sign in to comment.