Skip to content

Commit 6d5d73b

Browse files
committed
Contact page section is over!
1 parent d5e0dac commit 6d5d73b

File tree

9 files changed

+613
-16
lines changed

9 files changed

+613
-16
lines changed

src/common/components/input.tsx

Lines changed: 205 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,205 @@
1+
/**
2+
* @project CAC - https://github.com/cacybernetic/cacybernetic.github.io
3+
* @author Obrymec - https://obrymec.vercel.app
4+
* @fileoverview Defines input component.
5+
* @supported DESKTOP, MOBILE
6+
* @created 2025-07-14
7+
* @updated 2025-08-07
8+
* @file input.tsx
9+
* @version 0.0.1
10+
*/
11+
12+
// React dependencies.
13+
import {
14+
KeyboardEventHandler,
15+
ChangeEventHandler,
16+
useCallback,
17+
ElementType,
18+
useEffect,
19+
useState,
20+
useRef
21+
} from "react";
22+
23+
// Chakra dependencies.
24+
import {Text, Flex, Box} from "@chakra-ui/react";
25+
26+
// Custom dependencies.
27+
import {SF_REGULAR} from "@/common/constants/variables.ts";
28+
import {correctString} from "@/common/libraries/std.ts";
29+
30+
// Component property.
31+
export interface TextFieldProps {
32+
onKeyDown?: (event?: KeyboardEvent) => void,
33+
onChange: (value: string) => void,
34+
height?: (number | string),
35+
label: (string | null),
36+
placeholder?: string,
37+
mandatory?: boolean,
38+
charCount?: number,
39+
disabled?: boolean,
40+
mode?: ElementType,
41+
value?: string,
42+
error?: string,
43+
name?: string,
44+
type: string
45+
}
46+
47+
// Builds input component.
48+
export default function TextField ({
49+
placeholder,
50+
charCount,
51+
mandatory,
52+
onKeyDown,
53+
onChange,
54+
disabled,
55+
height,
56+
value,
57+
error,
58+
label,
59+
name,
60+
type,
61+
mode
62+
}: TextFieldProps) {
63+
// Attributes.
64+
const [isFocused, focus] = useState<boolean>(false);
65+
error = correctString<string>({input: error});
66+
const input = useRef<HTMLInputElement>(null);
67+
68+
// Called all time when input value get changed.
69+
const handleChange: ChangeEventHandler<HTMLInputElement> = (
70+
(event): void => onChange(event.target.value)
71+
);
72+
73+
// Called when a key is pressed while input has the focus.
74+
const onKeyPressed: KeyboardEventHandler<HTMLElement> = useCallback(
75+
(event): void => {
76+
// Whether `keydown` event is listening on the input.
77+
if (typeof onKeyDown === "function") onKeyDown(
78+
event as unknown as KeyboardEvent
79+
);
80+
// Dependencies.
81+
}, [onKeyDown]
82+
);
83+
84+
// When the component is rendered.
85+
useEffect((): void => {
86+
// Overrides input value.
87+
if (input.current != null) input.current.value = (value ?? '');
88+
// Dependencies.
89+
}, [value]);
90+
91+
// Builds tsx code.
92+
return <Box
93+
fontSize = {{base: 13, sm: 14, md: 15, lg: 16}}
94+
fontFamily = {SF_REGULAR}
95+
transition = "all .2s"
96+
userSelect = "none"
97+
width = "100%"
98+
>
99+
{/** Field */}
100+
<Flex
101+
transform = "translate3d(0, 0, 0)"
102+
backgroundColor = "neutral.1"
103+
width = "100%"
104+
>
105+
{/** Bottom border */}
106+
<Box
107+
backgroundColor = {error.length ? "error.500" : "primary.400"}
108+
right = {!isFocused ? "100%" : 0}
109+
left = {!isFocused ? "100%" : 0}
110+
transition = "all .3s"
111+
borderRadius = {4}
112+
position = "fixed"
113+
height = "2px"
114+
bottom = {0}
115+
/>
116+
{/** Input */}
117+
<Box
118+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
119+
// @ts-expect-error.
120+
maxLength = {Number.isInteger(charCount) ? charCount : undefined}
121+
id = {Math.floor(Math.random() * 1000000).toString()}
122+
as = {mode != null ? mode : "input"}
123+
onFocus = {(): void => focus(true)}
124+
onBlur = {(): void => focus(false)}
125+
placeholder = {placeholder}
126+
onKeyDown = {onKeyPressed}
127+
onChange = {handleChange}
128+
borderBottomWidth = {2}
129+
paddingBottom = "1rem"
130+
paddingInline = "1rem"
131+
transition = "all .2s"
132+
paddingTop = "0.9rem"
133+
disabled = {disabled}
134+
borderRight = "none"
135+
borderLeft = "none"
136+
borderRadius = {0}
137+
borderTop = "none"
138+
height = {height}
139+
outline = "none"
140+
resize = "none"
141+
width = "100%"
142+
type = {type}
143+
name = {name}
144+
ref = {input}
145+
borderBottomColor = {
146+
isFocused ? "transparent" :
147+
(error.length ? "error.500" : "neutral.5")
148+
}
149+
_hover = {{
150+
borderBottomColor: (
151+
isFocused ? "transparent" :
152+
(
153+
disabled ? "neutral.6" :
154+
(error.length ? "error.500" : "primary.200")
155+
)
156+
)
157+
}}
158+
/>
159+
{/** Label */}
160+
<Box
161+
transform = {mode == null ? "translateY(-50%)" : undefined}
162+
fontWeight = {isFocused ? "bold" : "normal"}
163+
pointerEvents = "none"
164+
transition = "all .2s"
165+
position = "absolute"
166+
paddingInline = {2}
167+
borderRadius = {4}
168+
paddingBlock = {1}
169+
left = "1rem"
170+
zIndex = {1}
171+
backgroundColor = {
172+
((value ?? '').length || isFocused) ? "neutral.2" : "neutral.1"
173+
}
174+
color = {
175+
error.length ? "error.500" :
176+
(isFocused ? "primary.400" : "neutral.10")
177+
}
178+
top = {
179+
mode == null ?
180+
(
181+
isFocused ? "-10%" :
182+
((value ?? '').length ? "-10%" : "50%")
183+
) :
184+
(
185+
isFocused ? "-1.3rem" :
186+
((value ?? '').length ? "-1.3rem" : "1rem")
187+
)
188+
}
189+
>
190+
{/** Content */}
191+
{label}
192+
{mandatory && <Text color = "error.500" as = "span"> *</Text>}
193+
</Box>
194+
</Flex>
195+
{/** Error message */}
196+
{error.length > 0 && <Text
197+
dangerouslySetInnerHTML = {{__html: error}}
198+
fontSize = {{base: 12, sm: 13, md: 14}}
199+
transition = "all .2s"
200+
color = "error.500"
201+
marginLeft = {4}
202+
marginTop = {3}
203+
/>}
204+
</Box>;
205+
}

src/common/components/section.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
* @author Obrymec - https://obrymec.vercel.app
55
* @supported DESKTOP, MOBILE
66
* @created 2025-07-30
7-
* @updated 2025-08-05
7+
* @updated 2025-08-07
88
* @file section.tsx
99
* @version 0.0.3
1010
*/
@@ -76,7 +76,7 @@ export default function Section ({
7676
userSelect = "none"
7777
width = "full"
7878
paddingBlock = {
79-
drawLines ? undefined : {base: 8, sm: 12, md: 16, lg: 20, xl: 24}
79+
drawLines ? undefined : {base: 8, sm: 12, md: 20, lg: 20, xl: 24}
8080
}
8181
{...containerStyle}
8282
>

src/common/constants/api_links.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
/**
22
* @project CAC - https://github.com/cacybernetic/cacybernetic.github.io
3-
* @fileoverview Contains all endpoints for remote APIs call.
3+
* @fileoverview Contains all end points for remote APIs call.
44
* @author Obrymec - https://obrymec.vercel.app
55
* @supported DESKTOP, MOBILE
66
* @created 2025-07-21
7-
* @updated 2025-07-21
7+
* @updated 2025-08-07
88
* @file api_links.ts
99
* @version 0.0.1
1010
*/

src/common/constants/storage_keys.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,16 @@
55
* @supported DESKTOP, MOBILE
66
* @file storage_keys.ts
77
* @created 2025-07-21
8-
* @updated 2025-07-21
9-
* @version 0.0.1
8+
* @updated 2025-08-07
9+
* @version 0.0.2
1010
*/
1111

1212
// Local storage keys.
13-
const LOGGED_USER_ID_SAVE_KEY: string = "app_logged_userid_sk";
14-
const REFRESH_TOKEN_SAVE_KEY: string = "app_refresh_token_sk";
15-
const ACCESS_TOKEN_SAVE_KEY: string = "app_access_token_sk";
16-
const ACTIVE_LANGUAGE_SAVE_KEY: string = "app_act_lang_sk";
13+
const LOGGED_USER_ID_SAVE_KEY: string = "ca_logged_userid_sk";
14+
const REFRESH_TOKEN_SAVE_KEY: string = "ca_refresh_token_sk";
15+
const ACCESS_TOKEN_SAVE_KEY: string = "ca_access_token_sk";
16+
const ACTIVE_LANGUAGE_SAVE_KEY: string = "ca_act_lang_sk";
17+
const CONTACT_SAVE_KEY: string = "ca_ct_sk";
1718

1819
/**
1920
* @description Exports only public features.
@@ -23,5 +24,6 @@ export {
2324
ACTIVE_LANGUAGE_SAVE_KEY,
2425
LOGGED_USER_ID_SAVE_KEY,
2526
REFRESH_TOKEN_SAVE_KEY,
26-
ACCESS_TOKEN_SAVE_KEY
27+
ACCESS_TOKEN_SAVE_KEY,
28+
CONTACT_SAVE_KEY
2729
};

src/common/constants/variables.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,18 @@
44
* @author Obrymec - https://obrymec.vercel.app
55
* @supported DESKTOP, MOBILE
66
* @created 2025-07-21
7-
* @updated 2025-07-22
7+
* @updated 2025-08-07
88
* @file variables.ts
9-
* @version 0.0.2
9+
* @version 0.0.3
1010
*/
1111

1212
// Responsive breakpoints.
1313
const BREAKPOINT_316: number = 316;
1414

15+
// Contact information.
16+
const COMPANY_GMAIL: string = "ca.cybernetic@gmail.com";
17+
const COMPANY_PHONE: string = "(+229) 019 798 5109";
18+
1519
// Font families.
1620
const POPPINS_SEMI_BOLD: string = "PoppinsSemiBold";
1721
const POPPINS_REGULAR: string = "PoppinsRegular";
@@ -32,6 +36,10 @@ export {
3236
// Responsive breakpoints.
3337
BREAKPOINT_316,
3438

39+
// Contact information.
40+
COMPANY_GMAIL,
41+
COMPANY_PHONE,
42+
3543
// Font families.
3644
POPPINS_SEMI_BOLD,
3745
POPPINS_REGULAR,

src/common/i18n/english.json

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,12 @@
3434
"expertiseDescription": "We bring together a team of product development and engineering experts, capable of offering unique expertise. From design to completion, we support your project every step of the way.",
3535
"networkOff": "It appears that your browser has just been set off the internet. Check your network accessories (WiFi, router, etc...) and make sure you are correctly connected to the internet.",
3636
"servicesQualityDescription": "We support companies and project creators in the design of innovative solutions combining excellence and performance.",
37+
"contactLeftDescription": "Do you have an ambitious project or challenge to tackle ? Let's discuss it together to find the best solution.",
3738
"contactInvitationDescription": "Contact our team to discuss your needs freely and discover how Console Art can effectively support you.",
3839
"requestLaunchError": "An error occurred while trying to contact the remote server. Check your internet connection and try again.",
3940
"technologicalExcellenceTitle": "Cutting-edge technology, essential driving force behind our commitment",
4041
"requestTimeoutDesc": "Unable to contact the remote server. Check your internet network then try again.",
42+
"sendMailError": "An unexpected and unknown error occurred while sending your email. Please try again.",
4143
"projectsBuildingStepsTitle": "Turn your visions into reality with a team passionate about innovation",
4244
"solidExpertiseTitle": "Proven expertise, dedicated to the success of your projects",
4345
"listenNeedTitle": "At your service to understand and fully meet your expectations",
@@ -48,26 +50,30 @@
4850
"trustedPartnerTitle": "A reliable ally for building a sustainable future",
4951
"servicesQualityTitle": "Let specialists take care of your requirements",
5052
"aiPartnerTitle": "Take your first steps in AI with an exceptional ally",
53+
"contactLeftTitle": "Let's turn your dreams into concrete achievements",
5154
"whoAreUsTitle": "A collective of visionaries and seasoned specialists",
5255
"successFulCopyToClipboard": "The content has been copy to clipboard.",
5356
"browserNotOnline": "Your browser is not connected to the Internet🙁.",
5457
"aiPipelineTitle": "Development of advanced digital vision processes",
5558
"copyToClipboardFailed": "Failed to copy content to the clipboard.",
5659
"ourHistoryTitle": "We have been building our adventure since 2022",
60+
"emailError": "The provided electronic mail address is incorrect.",
5761
"copyright": "Copyright© {old} - {new} Console Art Cybernetic LLC",
5862
"networkOn": "Your browser has just connected to the internet.",
63+
"sendMailSuccess": "Your message has been sent successfully.",
5964
"shortResultsTitle": "Reliable and long-lasting performance",
6065
"ourHeartOfOurFacultyTitle": "What defines us above all",
6166
"aiIntegrationTitle": "Mastery of LLM model integration",
62-
"digitalExpert": "Digital transformation specialists.",
6367
"aiCreationTitle": "Engineering of high-tech products",
68+
"digitalExpert": "Digital transformation specialists.",
6469
"operationalFlowTitle": "Mastering operational flows",
6570
"aiTrainingTitle": "Skills acquisition and mentoring",
6671
"softDevReviewTitle": "Review and quality control",
6772
"talkAboutYourProject": "Talk about your project",
6873
"servicesQualityWorth": "What are our values ?",
6974
"oursTrustedPartners": "Ours trusted partners",
7075
"imageLoadError": "Unable to load this image.",
76+
"fullNameInputLabel": "First and last name",
7177
"aiSolutionExpert": "AI Solution Experts",
7278
"youHaveAProject": "Have you a project ?",
7379
"companyDiversityTitle": "Heterogeneity",
@@ -78,16 +84,21 @@
7884
"whatIsCompanyTitle": "Who are us ?",
7985
"companyExcellenceTitle": "Mastery",
8086
"softDevDesignTitle": "Engineering",
87+
"messageInputLabel": "Your message",
8188
"softDevTrainingTitle": "Training",
89+
"emailInputLabel": "Email address",
8290
"contactUs": "Let's get in touch",
8391
"softDevTitle": "Programmation",
8492
"legalNotices": "Legal Notices",
8593
"networkError": "Network error",
94+
"contactUsTitle": "Contact us",
8695
"companyName": "CA Cybernetic",
8796
"gameDev": "Interactive Media",
8897
"ai": "Artificial Inteligence",
8998
"moreDetails": "More details",
99+
"sendMessage": "Send message",
90100
"oursValues": "Ours Values",
101+
"inputError": "Input error",
91102
"getInTouch": "Contact us",
92103
"expertise": "Expertise",
93104
"ourStory": "Our Story",

0 commit comments

Comments
 (0)