diff --git a/postgresTest/PROJECT1/__pycache__/forms.cpython-311.pyc b/postgresTest/PROJECT1/__pycache__/forms.cpython-311.pyc index 8ec5d4336fe99bbf4023b50e27d5a05d31a20302..800a0a9595da5492629e9a463b92a9b90f985786 100644 Binary files a/postgresTest/PROJECT1/__pycache__/forms.cpython-311.pyc and b/postgresTest/PROJECT1/__pycache__/forms.cpython-311.pyc differ diff --git a/postgresTest/PROJECT1/__pycache__/models.cpython-311.pyc b/postgresTest/PROJECT1/__pycache__/models.cpython-311.pyc index 2198e6f579183f0d627e8ea744b59016fba39080..e72cc5bd9c7eb627fe6bdfd8ca865a96ce478c58 100644 Binary files a/postgresTest/PROJECT1/__pycache__/models.cpython-311.pyc and b/postgresTest/PROJECT1/__pycache__/models.cpython-311.pyc differ diff --git a/postgresTest/PROJECT1/__pycache__/urls.cpython-311.pyc b/postgresTest/PROJECT1/__pycache__/urls.cpython-311.pyc index 471557d6700e6a4fc0031ca064a24fdf4f136254..ac31bcc5a84754d4d875498b3c996e1f102398c2 100644 Binary files a/postgresTest/PROJECT1/__pycache__/urls.cpython-311.pyc and b/postgresTest/PROJECT1/__pycache__/urls.cpython-311.pyc differ diff --git a/postgresTest/PROJECT1/__pycache__/views.cpython-311.pyc b/postgresTest/PROJECT1/__pycache__/views.cpython-311.pyc index 2a4904c7dfe3350cf6b9330d4cfba15495488931..9161c7ff07ccee54a6ad27e89806f7de6b7994e2 100644 Binary files a/postgresTest/PROJECT1/__pycache__/views.cpython-311.pyc and b/postgresTest/PROJECT1/__pycache__/views.cpython-311.pyc differ diff --git a/postgresTest/PROJECT1/admin/css/base.css b/postgresTest/PROJECT1/admin/css/base.css index 72f4ae169b30e7851f8a8a81b9bfa0ff4936f9de..73ea2cb9742d38b141a778858278fd4d8ddeb5e5 100644 --- a/postgresTest/PROJECT1/admin/css/base.css +++ b/postgresTest/PROJECT1/admin/css/base.css @@ -1,1138 +1,135 @@ -/* - DJANGO Admin styles -*/ - -/* VARIABLE DEFINITIONS */ -html[data-theme="light"], -:root { - --primary: #79aec8; - --secondary: #417690; - --accent: #f5dd5d; - --primary-fg: #fff; - - --body-fg: #333; - --body-bg: #fff; - --body-quiet-color: #666; - --body-loud-color: #000; - - --header-color: #ffc; - --header-branding-color: var(--accent); - --header-bg: var(--secondary); - --header-link-color: var(--primary-fg); - - --breadcrumbs-fg: #c4dce8; - --breadcrumbs-link-fg: var(--body-bg); - --breadcrumbs-bg: var(--primary); - - --link-fg: #417893; - --link-hover-color: #036; - --link-selected-fg: #5b80b2; - - --hairline-color: #e8e8e8; - --border-color: #ccc; - - --error-fg: #ba2121; - - --message-success-bg: #dfd; - --message-warning-bg: #ffc; - --message-error-bg: #ffefef; - - --darkened-bg: #f8f8f8; /* A bit darker than --body-bg */ - --selected-bg: #e4e4e4; /* E.g. selected table cells */ - --selected-row: #ffc; - - --button-fg: #fff; - --button-bg: var(--primary); - --button-hover-bg: #609ab6; - --default-button-bg: var(--secondary); - --default-button-hover-bg: #205067; - --close-button-bg: #747474; - --close-button-hover-bg: #333; - --delete-button-bg: #ba2121; - --delete-button-hover-bg: #a41515; - - --object-tools-fg: var(--button-fg); - --object-tools-bg: var(--close-button-bg); - --object-tools-hover-bg: var(--close-button-hover-bg); - - --font-family-primary: - -apple-system, - BlinkMacSystemFont, - "Segoe UI", - system-ui, - Roboto, - "Helvetica Neue", - Arial, - sans-serif, - "Apple Color Emoji", - "Segoe UI Emoji", - "Segoe UI Symbol", - "Noto Color Emoji"; - --font-family-monospace: - ui-monospace, - Menlo, - Monaco, - "Cascadia Mono", - "Segoe UI Mono", - "Roboto Mono", - "Oxygen Mono", - "Ubuntu Monospace", - "Source Code Pro", - "Fira Mono", - "Droid Sans Mono", - "Courier New", - monospace, - "Apple Color Emoji", - "Segoe UI Emoji", - "Segoe UI Symbol", - "Noto Color Emoji"; -} - -html, body { - height: 100%; -} - +/* General Settings */ body { - margin: 0; - padding: 0; - font-size: 0.875rem; font-family: var(--font-family-primary); - color: var(--body-fg); - background: var(--body-bg); -} - -/* LINKS */ - -a:link, a:visited { - color: var(--link-fg); - text-decoration: none; - transition: color 0.15s, background 0.15s; -} - -a:focus, a:hover { - color: var(--link-hover-color); -} - -a:focus { - text-decoration: underline; -} - -a img { - border: none; -} - -a.section:link, a.section:visited { - color: var(--header-link-color); - text-decoration: none; -} - -a.section:focus, a.section:hover { - text-decoration: underline; -} - -/* GLOBAL DEFAULTS */ - -p, ol, ul, dl { - margin: .2em 0 .8em 0; -} - -p { - padding: 0; - line-height: 140%; -} - -h1,h2,h3,h4,h5 { - font-weight: bold; -} - -h1 { - margin: 0 0 20px; - font-weight: 300; - font-size: 1.25rem; - color: var(--body-quiet-color); -} - -h2 { - font-size: 1rem; - margin: 1em 0 .5em 0; -} - -h2.subhead { - font-weight: normal; - margin-top: 0; -} - -h3 { - font-size: 0.875rem; - margin: .8em 0 .3em 0; - color: var(--body-quiet-color); - font-weight: bold; -} - -h4 { - font-size: 0.75rem; - margin: 1em 0 .8em 0; - padding-bottom: 3px; -} - -h5 { - font-size: 0.625rem; - margin: 1.5em 0 .5em 0; - color: var(--body-quiet-color); - text-transform: uppercase; - letter-spacing: 1px; -} - -ul > li { - list-style-type: square; - padding: 1px 0; -} - -li ul { - margin-bottom: 0; -} - -li, dt, dd { - font-size: 0.8125rem; - line-height: 1.25rem; -} - -dt { - font-weight: bold; - margin-top: 4px; -} - -dd { - margin-left: 0; -} - -form { - margin: 0; - padding: 0; -} - -fieldset { + background-color: #f5f5f5; margin: 0; - min-width: 0; - padding: 0; - border: none; - border-top: 1px solid var(--hairline-color); -} - -blockquote { - font-size: 0.6875rem; - color: #777; - margin-left: 2px; - padding-left: 10px; - border-left: 5px solid #ddd; -} - -code, pre { - font-family: var(--font-family-monospace); - color: var(--body-quiet-color); - font-size: 0.75rem; - overflow-x: auto; -} - -pre.literal-block { - margin: 10px; - background: var(--darkened-bg); - padding: 6px 8px; -} - -code strong { - color: #930; -} - -hr { - clear: both; - color: var(--hairline-color); - background-color: var(--hairline-color); - height: 1px; - border: none; - margin: 0; - padding: 0; - line-height: 1px; -} - -/* TEXT STYLES & MODIFIERS */ - -.small { - font-size: 0.6875rem; -} - -.mini { - font-size: 0.625rem; -} - -.help, p.help, form p.help, div.help, form div.help, div.help li { - font-size: 0.6875rem; - color: var(--body-quiet-color); -} - -div.help ul { - margin-bottom: 0; -} - -.help-tooltip { - cursor: help; -} - -p img, h1 img, h2 img, h3 img, h4 img, td img { - vertical-align: middle; -} - -.quiet, a.quiet:link, a.quiet:visited { - color: var(--body-quiet-color); - font-weight: normal; -} - -.clear { - clear: both; -} - -.nowrap { - white-space: nowrap; -} - -.hidden { - display: none !important; -} - -/* TABLES */ - -table { - border-collapse: collapse; - border-color: var(--border-color); -} - -td, th { - font-size: 0.8125rem; - line-height: 1rem; - border-bottom: 1px solid var(--hairline-color); - vertical-align: top; - padding: 8px; -} - -th { - font-weight: 600; - text-align: left; -} - -thead th, -tfoot td { - color: var(--body-quiet-color); - padding: 5px 10px; - font-size: 0.6875rem; - background: var(--body-bg); - border: none; - border-top: 1px solid var(--hairline-color); - border-bottom: 1px solid var(--hairline-color); -} - -tfoot td { - border-bottom: none; - border-top: 1px solid var(--hairline-color); -} - -thead th.required { - color: var(--body-loud-color); -} - -tr.alt { - background: var(--darkened-bg); -} - -tr:nth-child(odd), .row-form-errors { - background: var(--body-bg); -} - -tr:nth-child(even), -tr:nth-child(even) .errorlist, -tr:nth-child(odd) + .row-form-errors, -tr:nth-child(odd) + .row-form-errors .errorlist { - background: var(--darkened-bg); -} - -/* SORTABLE TABLES */ - -thead th { - padding: 5px 10px; - line-height: normal; - text-transform: uppercase; - background: var(--darkened-bg); -} - -thead th a:link, thead th a:visited { - color: var(--body-quiet-color); -} - -thead th.sorted { - background: var(--selected-bg); -} - -thead th.sorted .text { - padding-right: 42px; -} - -table thead th .text span { - padding: 8px 10px; - display: block; -} - -table thead th .text a { - display: block; - cursor: pointer; - padding: 8px 10px; -} - -table thead th .text a:focus, table thead th .text a:hover { - background: var(--selected-bg); -} - -thead th.sorted a.sortremove { - visibility: hidden; -} - -table thead th.sorted:hover a.sortremove { - visibility: visible; -} - -table thead th.sorted .sortoptions { - display: block; - padding: 9px 5px 0 5px; - float: right; - text-align: right; -} - -table thead th.sorted .sortpriority { - font-size: .8em; - min-width: 12px; - text-align: center; - vertical-align: 3px; - margin-left: 2px; - margin-right: 2px; -} - -table thead th.sorted .sortoptions a { - position: relative; - width: 14px; - height: 14px; - display: inline-block; - background: url(../img/sorting-icons.svg) 0 0 no-repeat; - background-size: 14px auto; -} - -table thead th.sorted .sortoptions a.sortremove { - background-position: 0 0; -} - -table thead th.sorted .sortoptions a.sortremove:after { - content: '\\'; - position: absolute; - top: -6px; - left: 3px; - font-weight: 200; - font-size: 1.125rem; - color: var(--body-quiet-color); -} - -table thead th.sorted .sortoptions a.sortremove:focus:after, -table thead th.sorted .sortoptions a.sortremove:hover:after { - color: var(--link-fg); -} - -table thead th.sorted .sortoptions a.sortremove:focus, -table thead th.sorted .sortoptions a.sortremove:hover { - background-position: 0 -14px; -} - -table thead th.sorted .sortoptions a.ascending { - background-position: 0 -28px; -} - -table thead th.sorted .sortoptions a.ascending:focus, -table thead th.sorted .sortoptions a.ascending:hover { - background-position: 0 -42px; -} - -table thead th.sorted .sortoptions a.descending { - top: 1px; - background-position: 0 -56px; -} - -table thead th.sorted .sortoptions a.descending:focus, -table thead th.sorted .sortoptions a.descending:hover { - background-position: 0 -70px; -} - -/* FORM DEFAULTS */ - -input, textarea, select, .form-row p, form .button { - margin: 2px 0; - padding: 2px 3px; - vertical-align: middle; - font-family: var(--font-family-primary); - font-weight: normal; - font-size: 0.8125rem; -} -.form-row div.help { - padding: 2px 3px; -} - -textarea { - vertical-align: top; -} - -input[type=text], input[type=password], input[type=email], input[type=url], -input[type=number], input[type=tel], textarea, select, .vTextField { - border: 1px solid var(--border-color); - border-radius: 4px; - padding: 5px 6px; - margin-top: 0; - color: var(--body-fg); - background-color: var(--body-bg); -} - -input[type=text]:focus, input[type=password]:focus, input[type=email]:focus, -input[type=url]:focus, input[type=number]:focus, input[type=tel]:focus, -textarea:focus, select:focus, .vTextField:focus { - border-color: var(--body-quiet-color); -} - -select { - height: 1.875rem; -} - -select[multiple] { - /* Allow HTML size attribute to override the height in the rule above. */ - height: auto; - min-height: 150px; -} - -/* FORM BUTTONS */ - -.button, input[type=submit], input[type=button], .submit-row input, a.button { - background: var(--button-bg); - padding: 10px 15px; - border: none; - border-radius: 4px; - color: var(--button-fg); - cursor: pointer; - transition: background 0.15s; -} - -a.button { - padding: 4px 5px; -} - -.button:active, input[type=submit]:active, input[type=button]:active, -.button:focus, input[type=submit]:focus, input[type=button]:focus, -.button:hover, input[type=submit]:hover, input[type=button]:hover { - background: var(--button-hover-bg); -} - -.button[disabled], input[type=submit][disabled], input[type=button][disabled] { - opacity: 0.4; -} - -.button.default, input[type=submit].default, .submit-row input.default { - border: none; - font-weight: 400; - background: var(--default-button-bg); -} - -.button.default:active, input[type=submit].default:active, -.button.default:focus, input[type=submit].default:focus, -.button.default:hover, input[type=submit].default:hover { - background: var(--default-button-hover-bg); -} - -.button[disabled].default, -input[type=submit][disabled].default, -input[type=button][disabled].default { - opacity: 0.4; -} - - -/* MODULES */ - -.module { - border: none; - margin-bottom: 30px; - background: var(--body-bg); -} - -.module p, .module ul, .module h3, .module h4, .module dl, .module pre { - padding-left: 10px; - padding-right: 10px; -} - -.module blockquote { - margin-left: 12px; -} - -.module ul, .module ol { - margin-left: 1.5em; -} - -.module h3 { - margin-top: .6em; -} - -.module h2, .module caption, .inline-group h2 { - margin: 0; - padding: 8px; - font-weight: 400; - font-size: 0.8125rem; - text-align: left; - background: var(--primary); - color: var(--header-link-color); -} - -.module caption, -.inline-group h2 { - font-size: 0.75rem; - letter-spacing: 0.5px; - text-transform: uppercase; -} - -.module table { - border-collapse: collapse; -} - -/* MESSAGES & ERRORS */ - -ul.messagelist { - padding: 0; - margin: 0; -} - -ul.messagelist li { - display: block; - font-weight: 400; - font-size: 0.8125rem; - padding: 10px 10px 10px 65px; - margin: 0 0 10px 0; - background: var(--message-success-bg) url(../img/icon-yes.svg) 40px 12px no-repeat; - background-size: 16px auto; - color: var(--body-fg); - word-break: break-word; -} - -ul.messagelist li.warning { - background: var(--message-warning-bg) url(../img/icon-alert.svg) 40px 14px no-repeat; - background-size: 14px auto; -} - -ul.messagelist li.error { - background: var(--message-error-bg) url(../img/icon-no.svg) 40px 12px no-repeat; - background-size: 16px auto; + padding: 20px; } -.errornote { - font-size: 0.875rem; - font-weight: 700; - display: block; - padding: 10px 12px; - margin: 0 0 10px 0; - color: var(--error-fg); - border: 1px solid var(--error-fg); - border-radius: 4px; +/* Container Styles */ +.cv-container { + display: flex; + max-width: 1000px; + margin: 0 auto; background-color: var(--body-bg); - background-position: 5px 12px; - overflow-wrap: break-word; + border-radius: 10px; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); + overflow: hidden; } -ul.errorlist { - margin: 0 0 4px; - padding: 0; - color: var(--error-fg); - background: var(--body-bg); +/* Sidebar Styling */ +.cv-sidebar { + width: 30%; + background-color: var(--secondary); + color: var(--primary-fg); + padding: 30px; + box-sizing: border-box; } -ul.errorlist li { - font-size: 0.8125rem; +.cv-photo img { + width: 150px; + height: 150px; + border-radius: 50%; display: block; - margin-bottom: 4px; - overflow-wrap: break-word; -} - -ul.errorlist li:first-child { - margin-top: 0; -} - -ul.errorlist li a { - color: inherit; - text-decoration: underline; -} - -td ul.errorlist { - margin: 0; - padding: 0; -} - -td ul.errorlist li { - margin: 0; -} - -.form-row.errors { - margin: 0; - border: none; - border-bottom: 1px solid var(--hairline-color); - background: none; -} - -.form-row.errors ul.errorlist li { - padding-left: 0; -} - -.errors input, .errors select, .errors textarea, -td ul.errorlist + input, td ul.errorlist + select, td ul.errorlist + textarea { - border: 1px solid var(--error-fg); -} - -.description { - font-size: 0.75rem; - padding: 5px 0 0 12px; -} - -/* BREADCRUMBS */ - -div.breadcrumbs { - background: var(--breadcrumbs-bg); - padding: 10px 40px; - border: none; - color: var(--breadcrumbs-fg); - text-align: left; -} - -div.breadcrumbs a { - color: var(--breadcrumbs-link-fg); -} - -div.breadcrumbs a:focus, div.breadcrumbs a:hover { - color: var(--breadcrumbs-fg); -} - -/* ACTION ICONS */ - -.viewlink, .inlineviewlink { - padding-left: 16px; - background: url(../img/icon-viewlink.svg) 0 1px no-repeat; -} - -.addlink { - padding-left: 16px; - background: url(../img/icon-addlink.svg) 0 1px no-repeat; -} - -.changelink, .inlinechangelink { - padding-left: 16px; - background: url(../img/icon-changelink.svg) 0 1px no-repeat; + margin: 0 auto 20px auto; } -.deletelink { - padding-left: 16px; - background: url(../img/icon-deletelink.svg) 0 1px no-repeat; +.cv-sidebar h3 { + margin-top: 30px; + border-bottom: 2px solid var(--accent); + padding-bottom: 5px; } -a.deletelink:link, a.deletelink:visited { - color: #CC3434; /* XXX Probably unused? */ +.cv-sidebar p { + margin-bottom: 15px; + line-height: 1.6; } -a.deletelink:focus, a.deletelink:hover { - color: #993333; /* XXX Probably unused? */ - text-decoration: none; +/* Main Content Styling */ +.cv-main { + width: 70%; + padding: 40px; + box-sizing: border-box; } -/* OBJECT TOOLS */ - -.object-tools { - font-size: 0.625rem; +.cv-main h1 { + font-size: 2rem; font-weight: bold; - padding-left: 0; - float: right; - position: relative; - margin-top: -48px; -} - -.object-tools li { - display: block; - float: left; - margin-left: 5px; - height: 1rem; -} - -.object-tools a { - border-radius: 15px; -} - -.object-tools a:link, .object-tools a:visited { - display: block; - float: left; - padding: 3px 12px; - background: var(--object-tools-bg); - color: var(--object-tools-fg); - font-weight: 400; - font-size: 0.6875rem; - text-transform: uppercase; - letter-spacing: 0.5px; -} - -.object-tools a:focus, .object-tools a:hover { - background-color: var(--object-tools-hover-bg); -} - -.object-tools a:focus{ - text-decoration: none; -} - -.object-tools a.viewsitelink, .object-tools a.addlink { - background-repeat: no-repeat; - background-position: right 7px center; - padding-right: 26px; -} - -.object-tools a.viewsitelink { - background-image: url(../img/tooltag-arrowright.svg); -} - -.object-tools a.addlink { - background-image: url(../img/tooltag-add.svg); + color: var(--body-loud-color); + margin-bottom: 5px; } -/* OBJECT HISTORY */ - -#change-history table { - width: 100%; +.cv-main h2 { + font-size: 1.25rem; + color: var(--accent); + margin-bottom: 30px; } -#change-history table tbody th { - width: 16em; +.cv-section { + margin-bottom: 40px; } -#change-history .paginator { - color: var(--body-quiet-color); - border-bottom: 1px solid var(--hairline-color); - background: var(--body-bg); - overflow: hidden; +.cv-section h3 { + font-size: 1.1rem; + color: var(--body-loud-color); + border-bottom: 2px solid var(--hairline-color); + padding-bottom: 10px; + margin-bottom: 20px; } -/* PAGE STRUCTURE */ - -#container { - position: relative; - width: 100%; - min-width: 980px; - padding: 0; +.form-group { + margin-bottom: 15px; display: flex; flex-direction: column; - height: 100%; -} - -#container > div { - flex-shrink: 0; -} - -#container > .main { - display: flex; - flex: 1 0 auto; -} - -.main > .content { - flex: 1 0; - max-width: 100%; -} - -.skip-to-content-link { - position: absolute; - top: -999px; - margin: 5px; - padding: 5px; - background: var(--body-bg); - z-index: 1; -} - -.skip-to-content-link:focus { - left: 0px; - top: 0px; } -#content { - padding: 20px 40px; -} - -.dashboard #content { - width: 600px; -} - -#content-main { - float: left; - width: 100%; -} - -#content-related { - float: right; - width: 260px; - position: relative; - margin-right: -300px; -} - -#footer { - clear: both; - padding: 10px; -} - -/* COLUMN TYPES */ - -.colMS { - margin-right: 300px; -} - -.colSM { - margin-left: 300px; -} - -.colSM #content-related { - float: left; - margin-right: 0; - margin-left: -300px; -} - -.colSM #content-main { - float: right; -} - -.popup .colM { - width: auto; -} - -/* HEADER */ - -#header { - width: auto; - height: auto; - display: flex; - justify-content: space-between; - align-items: center; - padding: 10px 40px; - background: var(--header-bg); - color: var(--header-color); - overflow: hidden; -} - -#header a:link, #header a:visited, #logout-form button { - color: var(--header-link-color); -} - -#header a:focus , #header a:hover { - text-decoration: underline; -} - -#branding { - display: flex; -} - -#branding h1 { - padding: 0; - margin: 0; - margin-inline-end: 20px; - font-weight: 300; - font-size: 1.5rem; - color: var(--header-branding-color); -} - -#branding h1 a:link, #branding h1 a:visited { - color: var(--accent); -} - -#branding h2 { - padding: 0 10px; - font-size: 0.875rem; - margin: -8px 0 8px 0; - font-weight: normal; - color: var(--header-color); -} - -#branding a:hover { - text-decoration: none; -} - -#logout-form { - display: inline; -} - -#logout-form button { - background: none; - border: 0; - cursor: pointer; - font-family: var(--font-family-primary); -} - -#user-tools { - float: right; - margin: 0 0 0 20px; - text-align: right; -} - -#user-tools, #logout-form button{ - padding: 0; - font-weight: 300; - font-size: 0.6875rem; - letter-spacing: 0.5px; - text-transform: uppercase; -} - -#user-tools a, #logout-form button { - border-bottom: 1px solid rgba(255, 255, 255, 0.25); -} - -#user-tools a:focus, #user-tools a:hover, -#logout-form button:active, #logout-form button:hover { - text-decoration: none; - border-bottom: 0; -} - -#logout-form button:active, #logout-form button:hover { - margin-bottom: 1px; -} - -/* SIDEBAR */ - -#content-related { - background: var(--darkened-bg); -} - -#content-related .module { - background: none; -} - -#content-related h3 { +.form-group label { + font-weight: 500; + margin-bottom: 5px; color: var(--body-quiet-color); - padding: 0 16px; - margin: 0 0 16px; -} - -#content-related h4 { - font-size: 0.8125rem; -} - -#content-related p { - padding-left: 16px; - padding-right: 16px; -} - -#content-related .actionlist { - padding: 0; - margin: 16px; -} - -#content-related .actionlist li { - line-height: 1.2; - margin-bottom: 10px; - padding-left: 18px; -} - -#content-related .module h2 { - background: none; - padding: 16px; - margin-bottom: 16px; - border-bottom: 1px solid var(--hairline-color); - font-size: 1.125rem; - color: var(--body-fg); } -.delete-confirmation form input[type="submit"] { - background: var(--delete-button-bg); - border-radius: 4px; - padding: 10px 15px; - color: var(--button-fg); -} - -.delete-confirmation form input[type="submit"]:active, -.delete-confirmation form input[type="submit"]:focus, -.delete-confirmation form input[type="submit"]:hover { - background: var(--delete-button-hover-bg); -} - -.delete-confirmation form .cancel-link { - display: inline-block; - vertical-align: middle; - height: 0.9375rem; - line-height: 0.9375rem; - border-radius: 4px; - padding: 10px 15px; - color: var(--button-fg); - background: var(--close-button-bg); - margin: 0 0 0 10px; -} - -.delete-confirmation form .cancel-link:active, -.delete-confirmation form .cancel-link:focus, -.delete-confirmation form .cancel-link:hover { - background: var(--close-button-hover-bg); -} - -/* POPUP */ -.popup #content { - padding: 20px; -} - -.popup #container { - min-width: 0; -} - -.popup #header { - padding: 10px 20px; -} - -/* PAGINATOR */ - -.paginator { - font-size: 0.8125rem; - padding-top: 10px; - padding-bottom: 10px; - line-height: 22px; - margin: 0; - border-top: 1px solid var(--hairline-color); - width: 100%; +.form-group input, +.form-group textarea, +.form-group select { + padding: 10px; + font-size: 16px; + border: 1px solid var(--border-color); + border-radius: 5px; + background-color: var(--darkened-bg); } -.paginator a:link, .paginator a:visited { - padding: 2px 6px; - background: var(--button-bg); - text-decoration: none; +.btn-primary { + background-color: var(--button-bg); color: var(--button-fg); -} - -.paginator a.showall { + padding: 15px; + font-size: 1rem; + text-transform: uppercase; + font-weight: bold; + text-align: center; border: none; - background: none; - color: var(--link-fg); -} - -.paginator a.showall:focus, .paginator a.showall:hover { - background: none; - color: var(--link-hover-color); + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s; } -.paginator .end { - margin-right: 6px; +.btn-primary:hover { + background-color: var(--button-hover-bg); } -.paginator .this-page { - padding: 2px 6px; - font-weight: bold; - font-size: 0.8125rem; - vertical-align: top; -} +/* Responsive Styles */ +@media (max-width: 768px) { + .cv-container { + flex-direction: column; + } -.paginator a:focus, .paginator a:hover { - color: white; - background: var(--link-hover-color); -} + .cv-sidebar { + width: 100%; + text-align: center; + } -.base-svgs { - display: none; + .cv-main { + width: 100%; + padding: 20px; + } } diff --git a/postgresTest/PROJECT1/admin/css/forms.css b/postgresTest/PROJECT1/admin/css/forms.css index e45abe1c07e9875c703d20bbf44890019fa8e1d5..68f6d98ed3f536030a420c77c82cf1c4d2b4c48a 100644 --- a/postgresTest/PROJECT1/admin/css/forms.css +++ b/postgresTest/PROJECT1/admin/css/forms.css @@ -1,530 +1,134 @@ -@import url('widgets.css'); - -/* FORM ROWS */ - -.form-row { - overflow: hidden; - padding: 10px; - font-size: 0.8125rem; - border-bottom: 1px solid var(--hairline-color); -} - -.form-row img, .form-row input { - vertical-align: middle; -} - -.form-row label input[type="checkbox"] { - margin-top: 0; - vertical-align: 0; -} - -form .form-row p { - padding-left: 0; +/* General Settings */ +body { + font-family: 'Roboto', sans-serif; + background-color: #f5f5f5; + margin: 0; + padding: 20px; } -.flex-container { +/* Container Styles */ +.cv-container { display: flex; - flex-wrap: wrap; -} - -.form-multiline > div { - padding-bottom: 10px; -} - -/* FORM LABELS */ - -label { - font-weight: normal; - color: var(--body-quiet-color); - font-size: 0.8125rem; -} - -.required label, label.required { - font-weight: bold; - color: var(--body-fg); -} - -/* RADIO BUTTONS */ - -form div.radiolist div { - padding-right: 7px; -} - -form div.radiolist.inline div { - display: inline-block; -} - -form div.radiolist label { - width: auto; -} - -form div.radiolist input[type="radio"] { - margin: -2px 4px 0 0; - padding: 0; -} - -form ul.inline { - margin-left: 0; - padding: 0; + max-width: 1000px; + margin: 0 auto; + background-color: #ffffff; + border-radius: 10px; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); + overflow: hidden; } -form ul.inline li { - float: left; - padding-right: 7px; +/* Sidebar Styling */ +.cv-sidebar { + width: 30%; + background-color: #2c3e50; + color: #ffffff; + padding: 30px; + box-sizing: border-box; } -/* ALIGNED FIELDSETS */ - -.aligned label { +.cv-photo img { + width: 150px; + height: 150px; + border-radius: 50%; display: block; - padding: 4px 10px 0 0; - width: 160px; - word-wrap: break-word; - line-height: 1; + margin: 0 auto 20px auto; } -.aligned label:not(.vCheckboxLabel):after { - content: ''; - display: inline-block; - vertical-align: middle; - height: 1.625rem; +.cv-sidebar h3 { + margin-top: 30px; + border-bottom: 2px solid #2980b9; + padding-bottom: 5px; } -.aligned label + p, .aligned .checkbox-row + div.help, .aligned label + div.readonly { - padding: 6px 0; - margin-top: 0; - margin-bottom: 0; - margin-left: 0; - overflow-wrap: break-word; +.cv-sidebar p { + margin-bottom: 15px; + line-height: 1.6; } -.aligned ul label { - display: inline; - float: none; - width: auto; +/* Main Content Styling */ +.cv-main { + width: 70%; + padding: 40px; + box-sizing: border-box; } -.aligned .form-row input { - margin-bottom: 0; -} - -.colMS .aligned .vLargeTextField, .colMS .aligned .vXMLLargeTextField { - width: 350px; -} - -form .aligned ul { - margin-left: 160px; - padding-left: 10px; -} - -form .aligned div.radiolist { - display: inline-block; - margin: 0; - padding: 0; -} - -form .aligned p.help, -form .aligned div.help { - margin-top: 0; - margin-left: 160px; - padding-left: 10px; -} - -form .aligned p.date div.help.timezonewarning, -form .aligned p.datetime div.help.timezonewarning, -form .aligned p.time div.help.timezonewarning { - margin-left: 0; - padding-left: 0; - font-weight: normal; -} - -form .aligned p.help:last-child, -form .aligned div.help:last-child { - margin-bottom: 0; - padding-bottom: 0; -} - -form .aligned input + p.help, -form .aligned textarea + p.help, -form .aligned select + p.help, -form .aligned input + div.help, -form .aligned textarea + div.help, -form .aligned select + div.help { - margin-left: 160px; - padding-left: 10px; -} - -form .aligned ul li { - list-style: none; -} - -form .aligned table p { - margin-left: 0; - padding-left: 0; -} - -.aligned .vCheckboxLabel { - float: none; - width: auto; - display: inline-block; - vertical-align: -3px; - padding: 0 0 5px 5px; -} - -.aligned .vCheckboxLabel + p.help, -.aligned .vCheckboxLabel + div.help { - margin-top: -4px; -} - -.colM .aligned .vLargeTextField, .colM .aligned .vXMLLargeTextField { - width: 610px; -} - -fieldset .fieldBox { - margin-right: 20px; -} - -/* WIDE FIELDSETS */ - -.wide label { - width: 200px; -} - -form .wide p, -form .wide ul.errorlist, -form .wide input + p.help, -form .wide input + div.help { - margin-left: 200px; -} - -form .wide p.help, -form .wide div.help { - padding-left: 50px; -} - -form div.help ul { - padding-left: 0; - margin-left: 0; -} - -.colM fieldset.wide .vLargeTextField, .colM fieldset.wide .vXMLLargeTextField { - width: 450px; -} - -/* COLLAPSED FIELDSETS */ - -fieldset.collapsed * { - display: none; -} - -fieldset.collapsed h2, fieldset.collapsed { - display: block; -} - -fieldset.collapsed { - border: 1px solid var(--hairline-color); - border-radius: 4px; - overflow: hidden; -} - -fieldset.collapsed h2 { - background: var(--darkened-bg); - color: var(--body-quiet-color); +.cv-main h1 { + font-size: 2rem; + font-weight: bold; + color: #34495e; + margin-bottom: 5px; } -fieldset .collapse-toggle { - color: var(--header-link-color); +.cv-main h2 { + font-size: 1.25rem; + color: #2980b9; + margin-bottom: 30px; } -fieldset.collapsed .collapse-toggle { - background: transparent; - display: inline; - color: var(--link-fg); +.cv-section { + margin-bottom: 40px; } -/* MONOSPACE TEXTAREAS */ - -fieldset.monospace textarea { - font-family: var(--font-family-monospace); +.cv-section h3 { + font-size: 1.1rem; + color: #2c3e50; + border-bottom: 2px solid #bdc3c7; + padding-bottom: 10px; + margin-bottom: 20px; } -/* SUBMIT ROW */ - -.submit-row { - padding: 12px 14px 12px; - margin: 0 0 20px; - background: var(--darkened-bg); - border: 1px solid var(--hairline-color); - border-radius: 4px; - overflow: hidden; +.form-group { + margin-bottom: 15px; display: flex; - gap: 10px; - flex-wrap: wrap; + flex-direction: column; } -body.popup .submit-row { - overflow: auto; +.form-group label { + font-weight: 500; + margin-bottom: 5px; + color: #7f8c8d; } -.submit-row input { - height: 2.1875rem; - line-height: 0.9375rem; -} - -.submit-row input, .submit-row a { - margin: 0; +.form-group input, +.form-group textarea, +.form-group select { + padding: 10px; + font-size: 16px; + border: 1px solid #bdc3c7; + border-radius: 5px; } -.submit-row input.default { +.btn-primary { + background-color: #27ae60; + color: #ffffff; + padding: 15px; + font-size: 1rem; text-transform: uppercase; -} - -.submit-row a.deletelink { - margin-left: auto; -} - -.submit-row a.deletelink { - display: block; - background: var(--delete-button-bg); - border-radius: 4px; - padding: 0.625rem 0.9375rem; - height: 0.9375rem; - line-height: 0.9375rem; - color: var(--button-fg); -} - -.submit-row a.closelink { - display: inline-block; - background: var(--close-button-bg); - border-radius: 4px; - padding: 10px 15px; - height: 0.9375rem; - line-height: 0.9375rem; - color: var(--button-fg); -} - -.submit-row a.deletelink:focus, -.submit-row a.deletelink:hover, -.submit-row a.deletelink:active { - background: var(--delete-button-hover-bg); - text-decoration: none; -} - -.submit-row a.closelink:focus, -.submit-row a.closelink:hover, -.submit-row a.closelink:active { - background: var(--close-button-hover-bg); - text-decoration: none; -} - -/* CUSTOM FORM FIELDS */ - -.vSelectMultipleField { - vertical-align: top; -} - -.vCheckboxField { - border: none; -} - -.vDateField, .vTimeField { - margin-right: 2px; - margin-bottom: 4px; -} - -.vDateField { - min-width: 6.85em; -} - -.vTimeField { - min-width: 4.7em; -} - -.vURLField { - width: 30em; -} - -.vLargeTextField, .vXMLLargeTextField { - width: 48em; -} - -.flatpages-flatpage #id_content { - height: 40.2em; -} - -.module table .vPositiveSmallIntegerField { - width: 2.2em; -} - -.vIntegerField { - width: 5em; -} - -.vBigIntegerField { - width: 10em; -} - -.vForeignKeyRawIdAdminField { - width: 5em; -} - -.vTextField, .vUUIDField { - width: 20em; -} - -/* INLINES */ - -.inline-group { - padding: 0; - margin: 0 0 30px; -} - -.inline-group thead th { - padding: 8px 10px; -} - -.inline-group .aligned label { - width: 160px; -} - -.inline-related { - position: relative; -} - -.inline-related h3 { - margin: 0; - color: var(--body-quiet-color); - padding: 5px; - font-size: 0.8125rem; - background: var(--darkened-bg); - border-top: 1px solid var(--hairline-color); - border-bottom: 1px solid var(--hairline-color); -} - -.inline-related h3 span.delete { - float: right; -} - -.inline-related h3 span.delete label { - margin-left: 2px; - font-size: 0.6875rem; -} - -.inline-related fieldset { - margin: 0; - background: var(--body-bg); - border: none; - width: 100%; -} - -.inline-related fieldset.module h3 { - margin: 0; - padding: 2px 5px 3px 5px; - font-size: 0.6875rem; - text-align: left; font-weight: bold; - background: #bcd; - color: var(--body-bg); -} - -.inline-group .tabular fieldset.module { + text-align: center; border: none; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s; } -.inline-related.tabular fieldset.module table { - width: 100%; - overflow-x: scroll; -} - -.last-related fieldset { - border: none; -} - -.inline-group .tabular tr.has_original td { - padding-top: 2em; -} - -.inline-group .tabular tr td.original { - padding: 2px 0 0 0; - width: 0; - _position: relative; -} - -.inline-group .tabular th.original { - width: 0px; - padding: 0; -} - -.inline-group .tabular td.original p { - position: absolute; - left: 0; - height: 1.1em; - padding: 2px 9px; - overflow: hidden; - font-size: 0.5625rem; - font-weight: bold; - color: var(--body-quiet-color); - _width: 700px; -} - -.inline-group ul.tools { - padding: 0; - margin: 0; - list-style: none; -} - -.inline-group ul.tools li { - display: inline; - padding: 0 5px; +.btn-primary:hover { + background-color: #219150; } -.inline-group div.add-row, -.inline-group .tabular tr.add-row td { - color: var(--body-quiet-color); - background: var(--darkened-bg); - padding: 8px 10px; - border-bottom: 1px solid var(--hairline-color); -} +/* Responsive Styles */ +@media (max-width: 768px) { + .cv-container { + flex-direction: column; + } -.inline-group .tabular tr.add-row td { - padding: 8px 10px; - border-bottom: 1px solid var(--hairline-color); -} - -.inline-group ul.tools a.add, -.inline-group div.add-row a, -.inline-group .tabular tr.add-row td a { - background: url(../img/icon-addlink.svg) 0 1px no-repeat; - padding-left: 16px; - font-size: 0.75rem; -} - -.empty-form { - display: none; -} - -/* RELATED FIELD ADD ONE / LOOKUP */ - -.related-lookup { - margin-left: 5px; - display: inline-block; - vertical-align: middle; - background-repeat: no-repeat; - background-size: 14px; -} - -.related-lookup { - width: 1rem; - height: 1rem; - background-image: url(../img/search.svg); -} - -form .related-widget-wrapper ul { - display: inline-block; - margin-left: 0; - padding-left: 0; -} + .cv-sidebar { + width: 100%; + text-align: center; + } -.clearable-file-input input { - margin-top: 0; + .cv-main { + width: 100%; + padding: 20px; + } } diff --git a/postgresTest/PROJECT1/forms.py b/postgresTest/PROJECT1/forms.py index fc1a406b4ba2178583e278ad6774626f67ae0597..b1575a913e768e3a2176e8db7846c410ed8b6633 100644 --- a/postgresTest/PROJECT1/forms.py +++ b/postgresTest/PROJECT1/forms.py @@ -1,11 +1,13 @@ +# forms.py + from django import forms from django.contrib.auth.forms import UserCreationForm from django.contrib.auth import get_user_model -from .models import Contact, CustomUser, Employee +from .models import Contact, CustomUser, Employee, Company from django.core.validators import RegexValidator, EmailValidator +from django.core.exceptions import ValidationError import datetime - # RoleAssignmentForm for assigning roles class RoleAssignmentForm(forms.ModelForm): class Meta: @@ -20,7 +22,6 @@ class RoleAssignmentForm(forms.ModelForm): ]) } - # CustomUserCreationForm for creating users with role and validation class CustomUserCreationForm(UserCreationForm): email = forms.EmailField( @@ -33,7 +34,6 @@ class CustomUserCreationForm(UserCreationForm): model = get_user_model() fields = UserCreationForm.Meta.fields + ('email',) # Ensure email is included in the form - # ContactForm with custom validation and widgets for collecting contact info class ContactForm(forms.ModelForm): class Meta: @@ -56,14 +56,34 @@ class ContactForm(forms.ModelForm): phone_validator(phone) return phone - # OnboardingForm with custom widgets and validation for employee onboarding class OnboardingForm(forms.ModelForm): - # Adding file fields for Police Report, ID card images (front and back), and CV - police_report = forms.FileField(required=True, label="Police Report") - id_card_front = forms.ImageField(required=True, label="ID Card (Front)") - id_card_back = forms.ImageField(required=True, label="ID Card (Back)") - cv = forms.FileField(required=True, label="CV (Resume)") + police_report = forms.FileField( + required=True, + label="Police Report", + widget=forms.ClearableFileInput(attrs={'accept': '.pdf'}) + ) + id_card_front = forms.ImageField( + required=True, + label="ID Card (Front)", + widget=forms.ClearableFileInput(attrs={'accept': 'image/png, image/jpeg'}) + ) + id_card_back = forms.ImageField( + required=True, + label="ID Card (Back)", + widget=forms.ClearableFileInput(attrs={'accept': 'image/png, image/jpeg'}) + ) + cv = forms.FileField( + required=True, + label="CV (Resume)", + widget=forms.ClearableFileInput(attrs={'accept': '.pdf'}) + ) + + skills = forms.CharField( + required=True, + widget=forms.Textarea(attrs={'class': 'form-control', 'placeholder': 'List of skills...'}), + label="Skills" + ) class Meta: model = Employee @@ -71,7 +91,7 @@ class OnboardingForm(forms.ModelForm): 'first_name', 'last_name', 'email', 'phone', 'address', 'department', 'job_title', 'start_date', 'date_of_birth', 'id_card_number', 'emergency_contact_name', 'emergency_contact_phone', - 'banking_information', 'police_report', 'id_card_front', 'id_card_back', 'cv' + 'banking_information', 'police_report', 'id_card_front', 'id_card_back', 'cv', 'skills' ] widgets = { 'first_name': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'First Name'}), @@ -89,6 +109,7 @@ class OnboardingForm(forms.ModelForm): 'banking_information': forms.Textarea(attrs={'class': 'form-control', 'placeholder': 'Banking Information (optional)'}), } + # Additional validation for email def clean_email(self): email = self.cleaned_data.get('email') @@ -129,3 +150,64 @@ class OnboardingForm(forms.ModelForm): ) phone_validator(emergency_contact_phone) return emergency_contact_phone + + # Server-side validation for file types + def clean_police_report(self): + police_report = self.cleaned_data.get('police_report') + if police_report: + if not police_report.name.lower().endswith('.pdf'): + raise ValidationError("Police Report must be a PDF file.") + return police_report + + def clean_cv(self): + cv = self.cleaned_data.get('cv') + if cv: + if not cv.name.lower().endswith('.pdf'): + raise ValidationError("CV must be a PDF file.") + return cv + + def clean_id_card_front(self): + id_card_front = self.cleaned_data.get('id_card_front') + if id_card_front: + if not id_card_front.content_type in ['image/png', 'image/jpeg']: + raise ValidationError("ID Card Front must be a PNG or JPG image.") + return id_card_front + + def clean_id_card_back(self): + id_card_back = self.cleaned_data.get('id_card_back') + if id_card_back: + if not id_card_back.content_type in ['image/png', 'image/jpeg']: + raise ValidationError("ID Card Back must be a PNG or JPG image.") + return id_card_back + +### New CompanyOnboardingForm for companies ### +class CompanyOnboardingForm(forms.ModelForm): + registration_number = forms.CharField( + required=True, + label="Registration Number", + widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Company Registration Number'}) + ) + contact_person = forms.CharField( + required=True, + label="Contact Person", + widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Contact Person'}) + ) + contact_email = forms.EmailField( + required=True, + label="Contact Email", + widget=forms.EmailInput(attrs={'class': 'form-control', 'placeholder': 'Contact Email'}) + ) + phone = forms.CharField( + required=True, + label="Phone", + widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Phone Number'}) + ) + address = forms.CharField( + required=True, + widget=forms.Textarea(attrs={'class': 'form-control', 'placeholder': 'Company Address'}), + label="Company Address" + ) + + class Meta: + model = Company # Now the form is using the Company model instead of CustomUser + fields = ['registration_number', 'contact_person', 'contact_email', 'phone', 'address'] diff --git a/postgresTest/PROJECT1/migrations/0023_employee_address_employee_banking_information_and_more.py b/postgresTest/PROJECT1/migrations/0023_employee_address_employee_banking_information_and_more.py new file mode 100644 index 0000000000000000000000000000000000000000..9e67b7e64d97a66ca3a4787c89aea3a448ed8c9c --- /dev/null +++ b/postgresTest/PROJECT1/migrations/0023_employee_address_employee_banking_information_and_more.py @@ -0,0 +1,74 @@ +# Generated by Django 5.0.6 on 2024-10-15 01:33 + +import django.core.validators +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('PROJECT1', '0022_rename_price_job_salary_employee_id_card_number_and_more'), + ] + + operations = [ + migrations.AddField( + model_name='employee', + name='address', + field=models.TextField(default='Unknown'), + preserve_default=False, + ), + migrations.AddField( + model_name='employee', + name='banking_information', + field=models.TextField(blank=True, null=True), + ), + migrations.AddField( + model_name='employee', + name='cv', + field=models.FileField(blank=True, null=True, upload_to='documents/cv/'), + ), + migrations.AddField( + model_name='employee', + name='date_of_birth', + field=models.DateField(default='2000-01-01'), + preserve_default=False, + ), + migrations.AddField( + model_name='employee', + name='emergency_contact_name', + field=models.CharField(default='Unknown', max_length=100), + preserve_default=False, + ), + migrations.AddField( + model_name='employee', + name='emergency_contact_phone', + field=models.CharField(default='Unknown', max_length=15, validators=[django.core.validators.RegexValidator(message="Emergency contact phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", regex='^\\+?1?\\d{9,15}$')]), + preserve_default=False, + ), + migrations.AddField( + model_name='employee', + name='id_card_back', + field=models.ImageField(blank=True, null=True, upload_to='documents/id_cards/'), + ), + migrations.AddField( + model_name='employee', + name='id_card_front', + field=models.ImageField(blank=True, null=True, upload_to='documents/id_cards/'), + ), + migrations.AddField( + model_name='employee', + name='phone', + field=models.CharField(default='Unknown', max_length=15, validators=[django.core.validators.RegexValidator(message="Phone number must be entered in the format: '+999999999'. Up to 15 digits allowed.", regex='^\\+?1?\\d{9,15}$')]), + preserve_default=False, + ), + migrations.AddField( + model_name='employee', + name='police_report', + field=models.FileField(blank=True, null=True, upload_to='documents/police_reports/'), + ), + migrations.AddField( + model_name='employee', + name='skills', + field=models.TextField(blank=True, help_text='Comma-separated list of skills.', null=True), + ), + ] diff --git a/postgresTest/PROJECT1/migrations/0024_company.py b/postgresTest/PROJECT1/migrations/0024_company.py new file mode 100644 index 0000000000000000000000000000000000000000..19dfb4a17169694680ac3ba2bff1475a260c37f7 --- /dev/null +++ b/postgresTest/PROJECT1/migrations/0024_company.py @@ -0,0 +1,25 @@ +# Generated by Django 5.0.6 on 2024-10-15 04:57 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('PROJECT1', '0023_employee_address_employee_banking_information_and_more'), + ] + + operations = [ + migrations.CreateModel( + name='Company', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('registration_number', models.CharField(max_length=50, unique=True)), + ('company_name', models.CharField(max_length=255)), + ('contact_person', models.CharField(max_length=100)), + ('contact_email', models.EmailField(max_length=254)), + ('contact_phone', models.CharField(max_length=15)), + ('address', models.TextField()), + ], + ), + ] diff --git a/postgresTest/PROJECT1/migrations/__pycache__/0023_employee_address_employee_banking_information_and_more.cpython-311.pyc b/postgresTest/PROJECT1/migrations/__pycache__/0023_employee_address_employee_banking_information_and_more.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c3e9f4285fe61b40b1d52756ad599e8b141272f3 Binary files /dev/null and b/postgresTest/PROJECT1/migrations/__pycache__/0023_employee_address_employee_banking_information_and_more.cpython-311.pyc differ diff --git a/postgresTest/PROJECT1/migrations/__pycache__/0024_company.cpython-311.pyc b/postgresTest/PROJECT1/migrations/__pycache__/0024_company.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..60973c4b6c77683bc359a6e97f9b22fc69b4aea2 Binary files /dev/null and b/postgresTest/PROJECT1/migrations/__pycache__/0024_company.cpython-311.pyc differ diff --git a/postgresTest/PROJECT1/models.py b/postgresTest/PROJECT1/models.py index bc825fb79d4755f887810cb39781d0a21a612241..046175bd44bf8540113cd2778379513252651f3c 100644 --- a/postgresTest/PROJECT1/models.py +++ b/postgresTest/PROJECT1/models.py @@ -37,6 +37,9 @@ class Employee(models.Model): id_card_back = models.ImageField(upload_to='documents/id_cards/', blank=True, null=True) cv = models.FileField(upload_to='documents/cv/', blank=True, null=True) + # Add the skills field + skills = models.TextField(blank=True, null=True, help_text="Comma-separated list of skills.") + def __str__(self): return f"{self.first_name} {self.last_name} - {self.department}" @@ -79,3 +82,14 @@ class Contact(models.Model): def __str__(self): return self.name + +class Company(models.Model): + registration_number = models.CharField(max_length=50, unique=True) + company_name = models.CharField(max_length=255) + contact_person = models.CharField(max_length=100) + contact_email = models.EmailField() + contact_phone = models.CharField(max_length=15) + address = models.TextField() + + def __str__(self): + return self.company_name \ No newline at end of file diff --git a/postgresTest/PROJECT1/templates/base.html b/postgresTest/PROJECT1/templates/base.html index 08784b217cec7cd2a52a7c76367888bf1453f257..5ccb007279cdbcca41c7040b8152e6fbbadaed3b 100644 --- a/postgresTest/PROJECT1/templates/base.html +++ b/postgresTest/PROJECT1/templates/base.html @@ -159,8 +159,10 @@ <a href="{% url 'employee_list' %}" class="list-group-item list-group-item-action bg-light"> <i class="fa fa-users" aria-hidden="true"></i> View Employees </a> - - <!-- Removed the Meetings link --> + + <a href="{% url 'onboard_company' %}" class="list-group-item list-group-item-action bg-light"> + <i class="fa fa-building" aria-hidden="true"></i> Onboard Company + </a> <a href="#" class="list-group-item list-group-item-action bg-light"> <i class="fa fa-cogs" aria-hidden="true"></i> Settings diff --git a/postgresTest/PROJECT1/templates/company_onboarding_success.html b/postgresTest/PROJECT1/templates/company_onboarding_success.html new file mode 100644 index 0000000000000000000000000000000000000000..6524ebe02dcf6e0e1632e500f3ba0af00a9067f2 --- /dev/null +++ b/postgresTest/PROJECT1/templates/company_onboarding_success.html @@ -0,0 +1,13 @@ +{% extends 'base.html' %} + +{% block title %} +Company Onboarding Success +{% endblock title %} + +{% block content %} +<div class="container"> + <h1>Company Onboarding Successful!</h1> + <p>Company <strong>{{ company.registration_number }}</strong> has been successfully onboarded.</p> + <a href="{% url 'dashboard' %}" class="btn btn-primary">Return to Dashboard</a> +</div> +{% endblock content %} diff --git a/postgresTest/PROJECT1/templates/onboard_company.html b/postgresTest/PROJECT1/templates/onboard_company.html new file mode 100644 index 0000000000000000000000000000000000000000..63d2a147c3e8f2ab59566e0f74ff1f2ed7d34693 --- /dev/null +++ b/postgresTest/PROJECT1/templates/onboard_company.html @@ -0,0 +1,55 @@ +{% extends 'base.html' %} + +{% block title %} +Onboard New Company +{% endblock title %} + +{% block content %} +<style> + .form-container { + max-width: 700px; + margin: 0 auto; + background-color: #f9f9f9; + padding: 20px; + border-radius: 10px; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); + } + .form-group { + margin-bottom: 15px; + } + .form-group label { + font-weight: bold; + } + .form-group input, + .form-group textarea { + width: 100%; + padding: 10px; + margin-top: 5px; + border-radius: 5px; + border: 1px solid #ccc; + } + .btn-primary { + background-color: #28a745; + color: white; + padding: 10px 20px; + border: none; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s; + } + .btn-primary:hover { + background-color: #218838; + } +</style> + +<div class="form-container"> + <h1>Onboard New Company</h1> + <form method="POST"> + {% csrf_token %} + {{ form.as_p }} + + <button type="submit" class="btn btn-primary">Submit</button> + </form> +</div> + +{% endblock content %} diff --git a/postgresTest/PROJECT1/templates/onboard_employee.html b/postgresTest/PROJECT1/templates/onboard_employee.html index cd7779ce4e272134d3da4fe458e40b6d023dd4a2..b9623e1930361d4735360f142dda68593282324b 100644 --- a/postgresTest/PROJECT1/templates/onboard_employee.html +++ b/postgresTest/PROJECT1/templates/onboard_employee.html @@ -7,99 +7,332 @@ Onboard New Employee {% endblock title %} {% block content %} -<h1>Onboard New Employee</h1> +<style> + /* General Settings */ + body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + background-color: #f5f5f5; + margin: 0; + padding: 20px; + } -<!-- Make sure to add enctype for file uploads --> -<form method="POST" enctype="multipart/form-data"> - {% csrf_token %} + /* Container Styles */ + .cv-container { + display: flex; + max-width: 1000px; + margin: 0 auto; + background-color: #ffffff; + border-radius: 10px; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); + overflow: hidden; + } - <div class="form-group"> - {{ form.first_name.label_tag }} - {{ form.first_name }} - </div> + /* Sidebar Styling */ + .cv-sidebar { + width: 30%; + background-color: #417690; + color: #ffffff; + padding: 30px; + box-sizing: border-box; + } - <div class="form-group"> - {{ form.last_name.label_tag }} - {{ form.last_name }} - </div> + .cv-photo { + text-align: center; + margin-bottom: 20px; + } - <div class="form-group"> - {{ form.email.label_tag }} - {{ form.email }} - </div> + .cv-photo img { + width: 150px; + height: 150px; + border-radius: 50%; + display: block; + margin: 0 auto 10px auto; + } - <div class="form-group"> - {{ form.phone.label_tag }} - {{ form.phone }} - </div> + .cv-photo input[type="file"] { + display: none; + } - <div class="form-group"> - {{ form.address.label_tag }} - {{ form.address }} - </div> + .cv-photo button { + background-color: #27ae60; + color: #ffffff; + padding: 10px 20px; + border: none; + border-radius: 5px; + cursor: pointer; + } - <div class="form-group"> - {{ form.department.label_tag }} - {{ form.department }} - </div> + .cv-sidebar h3 { + margin-top: 30px; + border-bottom: 2px solid #f5dd5d; + padding-bottom: 5px; + } - <div class="form-group"> - {{ form.job_title.label_tag }} - {{ form.job_title }} - </div> + .cv-sidebar input, .cv-sidebar textarea { + width: 100%; + padding: 10px; + font-size: 16px; + border: none; + border-radius: 5px; + margin-bottom: 15px; + color: #333; + box-sizing: border-box; + } - <div class="form-group"> - {{ form.start_date.label_tag }} - {{ form.start_date }} - </div> + /* Main Content Styling */ + .cv-main { + width: 70%; + padding: 40px; + box-sizing: border-box; + } - <div class="form-group"> - {{ form.date_of_birth.label_tag }} - {{ form.date_of_birth }} - </div> + .cv-main h1 { + font-size: 2rem; + font-weight: bold; + color: #333; + margin-bottom: 5px; + } - <div class="form-group"> - {{ form.id_card_number.label_tag }} - {{ form.id_card_number }} - </div> + .cv-main h2 { + font-size: 1.25rem; + color: #f5dd5d; + margin-bottom: 30px; + } - <div class="form-group"> - {{ form.emergency_contact_name.label_tag }} - {{ form.emergency_contact_name }} - </div> + .cv-section { + margin-bottom: 40px; + } - <div class="form-group"> - {{ form.emergency_contact_phone.label_tag }} - {{ form.emergency_contact_phone }} - </div> + .cv-section h3 { + font-size: 1.1rem; + color: #333; + border-bottom: 2px solid #e8e8e8; + padding-bottom: 10px; + margin-bottom: 20px; + } - <div class="form-group"> - {{ form.banking_information.label_tag }} - {{ form.banking_information }} - </div> + .form-group { + margin-bottom: 15px; + display: flex; + flex-direction: column; + } - <!-- File uploads for Police Report, ID card images (front and back), and CV --> - <div class="form-group"> - {{ form.police_report.label_tag }} - {{ form.police_report }} - </div> + .form-group label { + font-weight: 500; + margin-bottom: 5px; + color: #666; + } - <div class="form-group"> - {{ form.id_card_front.label_tag }} - {{ form.id_card_front }} - </div> + .form-group input, + .form-group textarea, + .form-group select { + padding: 10px; + font-size: 16px; + border: 1px solid #ccc; + border-radius: 5px; + background-color: #f8f8f8; + } - <div class="form-group"> - {{ form.id_card_back.label_tag }} - {{ form.id_card_back }} - </div> + .btn-primary { + background-color: #27ae60; + color: #ffffff; + padding: 15px; + font-size: 1rem; + text-transform: uppercase; + font-weight: bold; + text-align: center; + border: none; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s; + } + + .btn-primary:hover { + background-color: #219150; + } + + .error-message { + color: red; + font-size: 0.875rem; + margin-top: 5px; + } + + /* Responsive Styles */ + @media (max-width: 768px) { + .cv-container { + flex-direction: column; + } + + .cv-sidebar { + width: 100%; + text-align: center; + } + + .cv-main { + width: 100%; + padding: 20px; + } + } +</style> + +<div class="cv-container"> + <div class="cv-sidebar"> + <div class="cv-photo"> + <img id="profile-picture" src="{% static 'images/profile_placeholder.png' %}" alt="Profile Photo"> + <input type="file" id="profile-upload" accept="image/*"> + <button type="button" onclick="document.getElementById('profile-upload').click();">Upload Photo</button> + </div> + <h3>CONTACT</h3> + <input type="text" name="phone" placeholder="Phone Number" value="{{ form.phone.value }}"> + <input type="email" name="email" placeholder="Email Address" value="{{ form.email.value }}"> + <textarea name="address" placeholder="Residential Address">{{ form.address.value }}</textarea> + + <h3>EDUCATION</h3> + <input type="text" name="institution" placeholder="Institution" value="{{ form.institution.value }}"> + <input type="text" name="degree" placeholder="Highest Degree" value="{{ form.degree.value }}"> - <div class="form-group"> - {{ form.cv.label_tag }} - {{ form.cv }} + <h3>SKILLS</h3> + <input type="text" name="skill_1" placeholder="Skill 1"> + <input type="text" name="skill_2" placeholder="Skill 2"> + <input type="text" name="skill_3" placeholder="Skill 3"> </div> - <button type="submit" class="btn btn-primary">Submit</button> -</form> -<!-- End of Onboard New Employee Section --> + <form method="POST" enctype="multipart/form-data" class="cv-main"> + {% csrf_token %} + <h1>{{ form.first_name }} {{ form.last_name }}</h1> + <h2>{{ form.job_title }}</h2> + + <section class="cv-section"> + <h3>PROFILE</h3> + <p>Provide a summary or objectives for the employee.</p> + </section> + + <section class="cv-section"> + <h3>WORK EXPERIENCE</h3> + <div class="form-group"> + {{ form.start_date.label_tag }} + {{ form.start_date }} + {% if form.start_date.errors %} + <div class="error-message"> + {% for error in form.start_date.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + <div class="form-group"> + <label for="end_date">End Date</label> + <input type="date" id="end_date" name="end_date" class="form-control"> + </div> + <div class="form-group"> + <label for="job_description">Job Description</label> + <textarea id="job_description" name="job_description" class="form-control" placeholder="What did you do in this job?"></textarea> + </div> + </section> + + <section class="cv-section"> + <h3>EMERGENCY CONTACT</h3> + <div class="form-group"> + {{ form.emergency_contact_name.label_tag }} + {{ form.emergency_contact_name }} + {% if form.emergency_contact_name.errors %} + <div class="error-message"> + {% for error in form.emergency_contact_name.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + <div class="form-group"> + {{ form.emergency_contact_phone.label_tag }} + {{ form.emergency_contact_phone }} + {% if form.emergency_contact_phone.errors %} + <div class="error-message"> + {% for error in form.emergency_contact_phone.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + </section> + + <section class="cv-section"> + <h3>ID INFORMATION</h3> + <div class="form-group"> + {{ form.id_card_number.label_tag }} + {{ form.id_card_number }} + {% if form.id_card_number.errors %} + <div class="error-message"> + {% for error in form.id_card_number.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + <div class="form-group"> + {{ form.id_card_front.label_tag }} + {{ form.id_card_front }} + {% if form.id_card_front.errors %} + <div class="error-message"> + {% for error in form.id_card_front.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + <div class="form-group"> + {{ form.id_card_back.label_tag }} + {{ form.id_card_back }} + {% if form.id_card_back.errors %} + <div class="error-message"> + {% for error in form.id_card_back.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + </section> + + <section class="cv-section"> + <h3>DOCUMENTS</h3> + <div class="form-group"> + {{ form.cv.label_tag }} + {{ form.cv }} + {% if form.cv.errors %} + <div class="error-message"> + {% for error in form.cv.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + <div class="form-group"> + {{ form.police_report.label_tag }} + {{ form.police_report }} + {% if form.police_report.errors %} + <div class="error-message"> + {% for error in form.police_report.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + </section> + + <button type="submit" class="btn btn-primary">Submit</button> + </form> +</div> + +<script> + document.getElementById('profile-upload').addEventListener('change', function(event) { + const file = event.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = function(e) { + document.getElementById('profile-picture').src = e.target.result; + }; + reader.readAsDataURL(file); + } + }); +</script> {% endblock content %} diff --git a/postgresTest/PROJECT1/templates/onboarding_success.html b/postgresTest/PROJECT1/templates/onboarding_success.html new file mode 100644 index 0000000000000000000000000000000000000000..af2f79906bf8c8c64fcb9229a3093304c3fdac72 --- /dev/null +++ b/postgresTest/PROJECT1/templates/onboarding_success.html @@ -0,0 +1,326 @@ +{% extends 'base.html' %} +{% load custom_filters %} +{% load static %} + +{% block title %} +Onboard New Employee +{% endblock title %} + +{% block content %} +<style> + /* General Settings */ + body { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + background-color: #f5f5f5; + margin: 0; + padding: 20px; + } + + /* Container Styles */ + .cv-container { + display: flex; + max-width: 1000px; + margin: 0 auto; + background-color: #ffffff; + border-radius: 10px; + box-shadow: 0 0 20px rgba(0, 0, 0, 0.1); + overflow: hidden; + } + + /* Sidebar Styling */ + .cv-sidebar { + width: 30%; + background-color: #417690; + color: #ffffff; + padding: 30px; + box-sizing: border-box; + } + + .cv-photo { + text-align: center; + margin-bottom: 20px; + } + + .cv-photo img { + width: 150px; + height: 150px; + border-radius: 50%; + display: block; + margin: 0 auto 10px auto; + } + + .cv-photo input[type="file"] { + display: none; + } + + .cv-photo button { + background-color: #27ae60; + color: #ffffff; + padding: 10px 20px; + border: none; + border-radius: 5px; + cursor: pointer; + } + + .cv-sidebar h3 { + margin-top: 30px; + border-bottom: 2px solid #f5dd5d; + padding-bottom: 5px; + } + + .cv-sidebar p { + margin-bottom: 15px; + line-height: 1.6; + } + + /* Main Content Styling */ + .cv-main { + width: 70%; + padding: 40px; + box-sizing: border-box; + } + + .cv-main h1 { + font-size: 2rem; + font-weight: bold; + color: #333; + margin-bottom: 5px; + } + + .cv-main h2 { + font-size: 1.25rem; + color: #f5dd5d; + margin-bottom: 30px; + } + + .cv-section { + margin-bottom: 40px; + } + + .cv-section h3 { + font-size: 1.1rem; + color: #333; + border-bottom: 2px solid #e8e8e8; + padding-bottom: 10px; + margin-bottom: 20px; + } + + .form-group { + margin-bottom: 15px; + display: flex; + flex-direction: column; + } + + .form-group label { + font-weight: 500; + margin-bottom: 5px; + color: #666; + } + + .form-group input, + .form-group textarea, + .form-group select { + padding: 10px; + font-size: 16px; + border: 1px solid #ccc; + border-radius: 5px; + background-color: #f8f8f8; + } + + .btn-primary { + background-color: #27ae60; + color: #ffffff; + padding: 15px; + font-size: 1rem; + text-transform: uppercase; + font-weight: bold; + text-align: center; + border: none; + border-radius: 5px; + cursor: pointer; + transition: background-color 0.3s; + } + + .btn-primary:hover { + background-color: #219150; + } + + .error-message { + color: red; + font-size: 0.875rem; + margin-top: 5px; + } + + /* Responsive Styles */ + @media (max-width: 768px) { + .cv-container { + flex-direction: column; + } + + .cv-sidebar { + width: 100%; + text-align: center; + } + + .cv-main { + width: 100%; + padding: 20px; + } + } +</style> + +<div class="cv-container"> + <div class="cv-sidebar"> + <div class="cv-photo"> + <img id="profile-picture" src="{% static 'images/profile_placeholder.png' %}" alt="Profile Photo"> + <input type="file" id="profile-upload" accept="image/*"> + <button type="button" onclick="document.getElementById('profile-upload').click();">Upload Photo</button> + </div> + <div class="cv-contact"> + <h3>CONTACT</h3> + <p><strong>Phone:</strong> {{ form.phone }}</p> + <p><strong>Email:</strong> {{ form.email }}</p> + <p><strong>Address:</strong> {{ form.address }}</p> + </div> + <div class="cv-education"> + <h3>EDUCATION</h3> + <p><strong>Department:</strong> {{ form.department }}</p> + <p><strong>Job Title:</strong> {{ form.job_title }}</p> + </div> + <div class="cv-skills"> + <h3>SKILLS</h3> + <p>Include skills based on the job profile.</p> + </div> + </div> + + <form method="POST" enctype="multipart/form-data" class="cv-main"> + {% csrf_token %} + <h1>{{ form.first_name }} {{ form.last_name }}</h1> + <h2>{{ form.job_title }}</h2> + + <section class="cv-section"> + <h3>PROFILE</h3> + <p>Provide a summary or objectives for the employee.</p> + </section> + + <section class="cv-section"> + <h3>WORK EXPERIENCE</h3> + <div class="form-group"> + {{ form.start_date.label_tag }} + {{ form.start_date }} + {% if form.start_date.errors %} + <div class="error-message"> + {% for error in form.start_date.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + </section> + + <section class="cv-section"> + <h3>EMERGENCY CONTACT</h3> + <div class="form-group"> + {{ form.emergency_contact_name.label_tag }} + {{ form.emergency_contact_name }} + {% if form.emergency_contact_name.errors %} + <div class="error-message"> + {% for error in form.emergency_contact_name.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + <div class="form-group"> + {{ form.emergency_contact_phone.label_tag }} + {{ form.emergency_contact_phone }} + {% if form.emergency_contact_phone.errors %} + <div class="error-message"> + {% for error in form.emergency_contact_phone.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + </section> + + <section class="cv-section"> + <h3>ID INFORMATION</h3> + <div class="form-group"> + {{ form.id_card_number.label_tag }} + {{ form.id_card_number }} + {% if form.id_card_number.errors %} + <div class="error-message"> + {% for error in form.id_card_number.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + <div class="form-group"> + {{ form.id_card_front.label_tag }} + {{ form.id_card_front }} + {% if form.id_card_front.errors %} + <div class="error-message"> + {% for error in form.id_card_front.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + <div class="form-group"> + {{ form.id_card_back.label_tag }} + {{ form.id_card_back }} + {% if form.id_card_back.errors %} + <div class="error-message"> + {% for error in form.id_card_back.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + </section> + + <section class="cv-section"> + <h3>DOCUMENTS</h3> + <div class="form-group"> + {{ form.cv.label_tag }} + {{ form.cv }} + {% if form.cv.errors %} + <div class="error-message"> + {% for error in form.cv.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + <div class="form-group"> + {{ form.police_report.label_tag }} + {{ form.police_report }} + {% if form.police_report.errors %} + <div class="error-message"> + {% for error in form.police_report.errors %} + <p>{{ error }}</p> + {% endfor %} + </div> + {% endif %} + </div> + </section> + + <button type="submit" class="btn btn-primary">Submit</button> + </form> +</div> + +<script> + document.getElementById('profile-upload').addEventListener('change', function(event) { + const file = event.target.files[0]; + if (file) { + const reader = new FileReader(); + reader.onload = function(e) { + document.getElementById('profile-picture').src = e.target.result; + }; + reader.readAsDataURL(file); + } + }); +</script> +{% endblock content %} diff --git a/postgresTest/PROJECT1/urls.py b/postgresTest/PROJECT1/urls.py index 2227e392b7e7e027edbc19eedd9c0798636c8da1..7bc7a399680620097273a57d401df87e147d4bab 100644 --- a/postgresTest/PROJECT1/urls.py +++ b/postgresTest/PROJECT1/urls.py @@ -18,6 +18,8 @@ urlpatterns = [ path('employees/', views.employee_list, name='employee_list'), path('edit-role/<int:user_id>/', edit_role, name='edit_role'), path('onboard/', views.onboard_employee, name='onboard_employee'), - path('onboarding-success/', views.onboarding_success, name='onboarding_success'), - path('dashboard/', views.dashboard, name='dashboard') + path('onboarding-success/<int:employee_id>/', views.onboarding_success, name='onboarding_success'), + path('dashboard/', views.dashboard, name='dashboard'), + path('onboard-company/', views.onboard_company, name='onboard_company'), + path('company-onboarding-success/<int:company_id>/', views.company_onboarding_success, name='company_onboarding_success') ] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/postgresTest/PROJECT1/views.py b/postgresTest/PROJECT1/views.py index 7581dcbc3706c148356634d1656300a68356a434..f737b59cf30e498b211208824ba075fc6971ab6d 100644 --- a/postgresTest/PROJECT1/views.py +++ b/postgresTest/PROJECT1/views.py @@ -2,8 +2,9 @@ from django.shortcuts import render, redirect, get_object_or_404 from django.contrib.auth import authenticate, login as auth_login, logout as auth_logout from django.contrib.auth.decorators import login_required from django.contrib import messages -from .models import Job, CustomUser -from .forms import CustomUserCreationForm, ContactForm, RoleAssignmentForm, OnboardingForm +from .models import Job, CustomUser, Employee, Company +from .forms import CustomUserCreationForm, ContactForm, RoleAssignmentForm, OnboardingForm,CompanyOnboardingForm + from django.contrib.auth.views import LoginView from django.contrib.auth.forms import UserChangeForm from django.http import HttpResponseForbidden @@ -21,17 +22,20 @@ def onboard_employee(request): return HttpResponseForbidden("You don't have permission to onboard employees.") if request.method == 'POST': - form = OnboardingForm(request.POST) + form = OnboardingForm(request.POST, request.FILES) if form.is_valid(): employee = form.save() - # Example: Logging action without exposing sensitive information + # Logging action (optional) print(f"New employee onboarded: {employee.first_name} {employee.last_name}") messages.success(request, 'Employee has been successfully onboarded.') - return redirect('onboarding_success') + # Redirect to the success page with employee ID + return redirect('onboarding_success', employee_id=employee.id) else: + # Print form errors for debugging + print(form.errors) messages.error(request, 'Please correct the errors below.') else: form = OnboardingForm() @@ -40,8 +44,10 @@ def onboard_employee(request): @login_required -def onboarding_success(request): - return render(request, 'onboarding_success.html') +def onboarding_success(request, employee_id): + # Query the Employee object based on the ID passed + employee = get_object_or_404(Employee, id=employee_id) + return render(request, 'onboarding_success.html', {'employee': employee}) @login_required @@ -167,3 +173,29 @@ def custom_login(request): else: messages.error(request, 'Invalid credentials') return render(request, 'login.html') + +@login_required +def onboard_company(request): + if not request.user.is_staff: + return HttpResponseForbidden("You don't have permission to onboard companies.") + + if request.method == 'POST': + form = CompanyOnboardingForm(request.POST) + if form.is_valid(): + company = form.save() + # Logging to verify + print(f"New company onboarded: {company.registration_number}") + + messages.success(request, 'Company has been successfully onboarded.') + return redirect('company_onboarding_success', company_id=company.id) + else: + messages.error(request, 'Please correct the errors below.') + else: + form = CompanyOnboardingForm() + + return render(request, 'onboard_company.html', {'form': form}) + +@login_required +def company_onboarding_success(request, company_id): + company = get_object_or_404(Company, id=company_id) + return render(request, 'company_onboarding_success.html', {'company': company}) \ No newline at end of file