import React, { useState, useEffect } from 'react';
interface Props {
initialCount?: number;
}
const Counter: React.FC<Props> = ({ initialCount = 0 }) => {
const [count, setCount] = useState<number>(initialCount);
const [status, setStatus] = useState<'idle' | 'incrementing' | 'decrementing'>('idle');
useEffect(() => {
if (status !== 'idle') {
console.log(`Status changed to ${status}`);
}
}, [status]);
const increment = () => {
setStatus('incrementing');
setCount((prevCount) => prevCount + 1);
setTimeout(() => setStatus('idle'), 500);
};
const decrement = () => {
setStatus('decrementing');
setCount((prevCount) => prevCount - 1);
setTimeout(() => setStatus('idle'), 500);
};
return (
<div>
<h1>Counter: {count}</h1>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<p>Status: {status}</p>
</div>
);
};
export default Counter;
// Controller
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/counter")
public class CounterController {
private int count = 0;
private String status = "idle";
@GetMapping
public CounterResponse getCounter() {
return new CounterResponse(count, status);
}
@PostMapping("/increment")
public CounterResponse increment() {
status = "incrementing";
count++;
resetStatus();
return new CounterResponse(count, status);
}
@PostMapping("/decrement")
public CounterResponse decrement() {
status = "decrementing";
count--;
resetStatus();
return new CounterResponse(count, status);
}
private void resetStatus() {
new java.util.Timer().schedule(new java.util.TimerTask() {
@Override
public void run() {
status = "idle";
}
}, 500); // 500ms delay to reset status
}
static class CounterResponse {
private final int count;
private final String status;
public CounterResponse(int count, String status) {
this.count = count;
this.status = status;
}
public int getCount() {
return count;
}
public String getStatus() {
return status;
}
}
}
---
import { text } from "./matrix.json";
---
<style>
/* Animación para el efecto de escritura */
@keyframes typing {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes vertical-marquee {
0% {
transform: translateY(100%);
}
100% {
transform: translateY(-100%);
}
}
/* Aplicar la animación de typing */
.vertical-marquee-container {
display: flex;
flex-direction: column;
height: 200px;
animation: vertical-marquee 10s linear infinite;
}
.vertical-marquee-content {
display: flex;
flex-direction: column;
gap: 8px; /* Espacio entre líneas */
}
.vertical-fade-line {
opacity: 0;
animation: typing 1s forwards; /* Ajusta la duración del efecto de escritura */
}
</style>
<div
class="w-full h-full max-w-full max-h-full text-cardHighlight dark:text-green-300 font-mono p-4 overflow-hidden"
>
<div class="vertical-marquee-container">
<div class="vertical-marquee-content">
<!-- Renderizado del texto línea por línea con efecto de aparición -->
{
text &&
text.length > 0 &&
text.map((line, lineIndex) => (
<div
class="whitespace-pre-line vertical-fade-line"
style={`animation-delay: ${lineIndex * 0.5}s`}
>
{line}
</div>
))
}
</div>
</div>
</div>
import React, { useState, useEffect } from 'react';
interface Props {
initialCount?: number;
}
const Counter: React.FC<Props> = ({ initialCount = 0 }) => {
const [count, setCount] = useState<number>(initialCount);
const [status, setStatus] = useState<'idle' | 'incrementing' | 'decrementing'>('idle');
useEffect(() => {
if (status !== 'idle') {
console.log(`Status changed to ${status}`);
}
}, [status]);
const increment = () => {
setStatus('incrementing');
setCount((prevCount) => prevCount + 1);
setTimeout(() => setStatus('idle'), 500);
};
const decrement = () => {
setStatus('decrementing');
setCount((prevCount) => prevCount - 1);
setTimeout(() => setStatus('idle'), 500);
};
return (
<div>
<h1>Counter: {count}</h1>
<button onClick={increment}>Increment</button>
<button onClick={decrement}>Decrement</button>
<p>Status: {status}</p>
</div>
);
};
export default Counter;
// Controller
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/counter")
public class CounterController {
private int count = 0;
private String status = "idle";
@GetMapping
public CounterResponse getCounter() {
return new CounterResponse(count, status);
}
@PostMapping("/increment")
public CounterResponse increment() {
status = "incrementing";
count++;
resetStatus();
return new CounterResponse(count, status);
}
@PostMapping("/decrement")
public CounterResponse decrement() {
status = "decrementing";
count--;
resetStatus();
return new CounterResponse(count, status);
}
private void resetStatus() {
new java.util.Timer().schedule(new java.util.TimerTask() {
@Override
public void run() {
status = "idle";
}
}, 500); // 500ms delay to reset status
}
static class CounterResponse {
private final int count;
private final String status;
public CounterResponse(int count, String status) {
this.count = count;
this.status = status;
}
public int getCount() {
return count;
}
public String getStatus() {
return status;
}
}
}
---
import { text } from "./matrix.json";
---
<style>
/* Animación para el efecto de escritura */
@keyframes typing {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
@keyframes vertical-marquee {
0% {
transform: translateY(100%);
}
100% {
transform: translateY(-100%);
}
}
/* Aplicar la animación de typing */
.vertical-marquee-container {
display: flex;
flex-direction: column;
height: 200px;
animation: vertical-marquee 10s linear infinite;
}
.vertical-marquee-content {
display: flex;
flex-direction: column;
gap: 8px; /* Espacio entre líneas */
}
.vertical-fade-line {
opacity: 0;
animation: typing 1s forwards; /* Ajusta la duración del efecto de escritura */
}
</style>
<div
class="w-full h-full max-w-full max-h-full text-cardHighlight dark:text-green-300 font-mono p-4 overflow-hidden"
>
<div class="vertical-marquee-container">
<div class="vertical-marquee-content">
<!-- Renderizado del texto línea por línea con efecto de aparición -->
{
text &&
text.length > 0 &&
text.map((line, lineIndex) => (
<div
class="whitespace-pre-line vertical-fade-line"
style={`animation-delay: ${lineIndex * 0.5}s`}
>
{line}
</div>
))
}
</div>
</div>
</div>

Relevant Content:

Other Knowledge:

View CV