diff --git a/epictrack-api/migrations/versions/08209ce361c2_add_eac_signed_and_expires_fields_to_.py b/epictrack-api/migrations/versions/08209ce361c2_add_eac_signed_and_expires_fields_to_.py
new file mode 100644
index 000000000..5d6398a02
--- /dev/null
+++ b/epictrack-api/migrations/versions/08209ce361c2_add_eac_signed_and_expires_fields_to_.py
@@ -0,0 +1,40 @@
+"""add eac signed and expires fields to project
+
+Revision ID: 08209ce361c2
+Revises: 19227722dffc
+Create Date: 2024-08-29 08:45:46.100404
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = '08209ce361c2'
+down_revision = '19227722dffc'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ with op.batch_alter_table('projects', schema=None) as batch_op:
+ batch_op.add_column(sa.Column('eac_signed', sa.Date(), nullable=True))
+ batch_op.add_column(sa.Column('eac_expires', sa.Date(), nullable=True))
+
+ with op.batch_alter_table('projects_history', schema=None) as batch_op:
+ batch_op.add_column(sa.Column('eac_signed', sa.Date(), autoincrement=False, nullable=True))
+ batch_op.add_column(sa.Column('eac_expires', sa.Date(), autoincrement=False, nullable=True))
+ # ### end Alembic commands ###
+
+
+def downgrade():
+ # ### commands auto generated by Alembic - please adjust! ###
+ with op.batch_alter_table('projects_history', schema=None) as batch_op:
+ batch_op.drop_column('eac_expires')
+ batch_op.drop_column('eac_signed')
+
+ with op.batch_alter_table('projects', schema=None) as batch_op:
+ batch_op.drop_column('eac_expires')
+ batch_op.drop_column('eac_signed')
+ # ### end Alembic commands ###
diff --git a/epictrack-api/src/api/models/project.py b/epictrack-api/src/api/models/project.py
index 0ba06e1e8..aa4026d30 100644
--- a/epictrack-api/src/api/models/project.py
+++ b/epictrack-api/src/api/models/project.py
@@ -14,7 +14,7 @@
"""Model to manage Project."""
import enum
-from sqlalchemy import Boolean, Column, Enum, Float, ForeignKey, Integer, String, Text, func
+from sqlalchemy import Boolean, Column, Date, Enum, Float, ForeignKey, Integer, String, Text, func
from sqlalchemy.orm import relationship
from .base_model import BaseModelVersioned
@@ -64,6 +64,8 @@ class Project(BaseModelVersioned):
region_id_env = Column(ForeignKey("regions.id"), nullable=True)
region_id_flnro = Column(ForeignKey("regions.id"), nullable=True)
abbreviation = Column(String(10), nullable=True, unique=True)
+ eac_signed = Column(Date(), nullable=True)
+ eac_expires = Column(Date(), nullable=True)
sub_type = relationship("SubType", foreign_keys=[sub_type_id], lazy="select")
type = relationship("Type", foreign_keys=[type_id], lazy="select")
proponent = relationship("Proponent", foreign_keys=[proponent_id], lazy="select")
diff --git a/epictrack-api/src/api/schemas/request/project_request.py b/epictrack-api/src/api/schemas/request/project_request.py
index e0c70a248..bbd6962b1 100644
--- a/epictrack-api/src/api/schemas/request/project_request.py
+++ b/epictrack-api/src/api/schemas/request/project_request.py
@@ -118,6 +118,18 @@ class ProjectBodyParameterSchema(RequestBodyParameterSchema):
load_default=None
)
+ eac_signed = fields.Date(
+ metadata={"description": "Date the EAC was signed on"},
+ allow_none=True,
+ load_default=None
+ )
+
+ eac_expires = fields.Date(
+ metadata={"description": "Date the EAC expires on"},
+ allow_none=True,
+ load_default=None
+ )
+
is_active = fields.Bool(metadata={"description": "Active state of the project"})
is_project_closed = fields.Bool(metadata={"description": "Closed state of the project"}, default=False)
diff --git a/epictrack-web/src/components/project/Dialog/index.tsx b/epictrack-web/src/components/project/Dialog/index.tsx
index c1b872cc4..15ded778d 100644
--- a/epictrack-web/src/components/project/Dialog/index.tsx
+++ b/epictrack-web/src/components/project/Dialog/index.tsx
@@ -67,6 +67,12 @@ export const ProjectDialog = ({
};
const saveProject = async (data: any) => {
+ if (data.eac_signed) {
+ data.eac_signed = new Date(data.eac_signed).toISOString().split("T")[0];
+ }
+ if (data.eac_expires) {
+ data.eac_expires = new Date(data.eac_expires).toISOString().split("T")[0];
+ }
if (projectId) {
await editProject(data);
} else {
diff --git a/epictrack-web/src/components/project/ProjectForm/index.tsx b/epictrack-web/src/components/project/ProjectForm/index.tsx
index 986f4ed5e..a06211a4f 100644
--- a/epictrack-web/src/components/project/ProjectForm/index.tsx
+++ b/epictrack-web/src/components/project/ProjectForm/index.tsx
@@ -26,6 +26,7 @@ import typeService from "services/typeService";
import proponentService from "services/proponentService/proponentService";
import { useAppSelector } from "hooks";
import { sort } from "utils";
+import ControlledDatePicker from "components/shared/controlledInputComponents/ControlledDatePicker";
const schema = yup.object().shape({
name: yup
@@ -449,6 +450,20 @@ export default function ProjectForm({
/>
+
+ EAC Signed
+
+
+
+ EAC Expires
+
+